/*
Copyright (c) 2024 Bytedance Ltd. and/or its affiliates
This file is part of ByteQC.

ByteQC includes code adapted from PySCF (https://github.com/pyscf/pyscf)
and GPU4PySCF (https://github.com/bytedance/gpu4pyscf),
which are licensed under the Apache License 2.0.
The original copyright:
    Copyright 2014-2020 The GPU4PySCF/PySCF Developers. All Rights Reserved.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

#include "rys_xw.cuh"
#include "roots_for_x0.cuh"

#define SQRTPIE4 .8862269254527580136
#define PIE4 .7853981633974483096

#define FP1(y)                  p[0]
#define FP2(y)                 (p[0]*y+p[1])
#define FP3(y)                ((p[0]*y+p[1])*y+p[2])
#define FP4(y)               (((p[0]*y+p[1])*y+p[2])*y+p[3])
#define FP5(y)              ((((p[0]*y+p[1])*y+p[2])*y+p[3])*y+p[4])
#define FP6(y)             (((((p[0]*y+p[1])*y+p[2])*y+p[3])*y+p[4])*y+p[5])
#define FP7(y)            ((((((p[0]*y+p[1])*y+p[2])*y+p[3])*y+p[4])*y+p[5])*y+p[6])
#define FP8(y)           (((((((p[0]*y+p[1])*y+p[2])*y+p[3])*y+p[4])*y+p[5])*y+p[6])*y+p[7])
#define FP9(y)          ((((((((p[0]*y+p[1])*y+p[2])*y+p[3])*y+p[4])*y+p[5])*y+p[6])*y+p[7])*y+p[8])
#define FP10(y)        (((((((((p[0]*y+p[1])*y+p[2])*y+p[3])*y+p[4])*y+p[5])*y+p[6])*y+p[7])*y+p[8])*y+p[9])
#define FP11(y)       ((((((((((p[0]*y+p[1])*y+p[2])*y+p[3])*y+p[4])*y+p[5])*y+p[6])*y+p[7])*y+p[8])*y+p[9])*y+p[10])
#define FP12(y)      (((((((((((p[0]*y+p[1])*y+p[2])*y+p[3])*y+p[4])*y+p[5])*y+p[6])*y+p[7])*y+p[8])*y+p[9])*y+p[10])*y+p[11])
#define FP13(y)     ((((((((((((p[0]*y+p[1])*y+p[2])*y+p[3])*y+p[4])*y+p[5])*y+p[6])*y+p[7])*y+p[8])*y+p[9])*y+p[10])*y+p[11])*y+p[12])
#define FP14(y)    (((((((((((((p[0]*y+p[1])*y+p[2])*y+p[3])*y+p[4])*y+p[5])*y+p[6])*y+p[7])*y+p[8])*y+p[9])*y+p[10])*y+p[11])*y+p[12])*y+p[13])
#define FP15(y)   ((((((((((((((p[0]*y+p[1])*y+p[2])*y+p[3])*y+p[4])*y+p[5])*y+p[6])*y+p[7])*y+p[8])*y+p[9])*y+p[10])*y+p[11])*y+p[12])*y+p[13])*y+p[14])
#define FP16(y)  (((((((((((((((p[0]*y+p[1])*y+p[2])*y+p[3])*y+p[4])*y+p[5])*y+p[6])*y+p[7])*y+p[8])*y+p[9])*y+p[10])*y+p[11])*y+p[12])*y+p[13])*y+p[14])*y+p[15])
#define FP17(y) ((((((((((((((((p[0]*y+p[1])*y+p[2])*y+p[3])*y+p[4])*y+p[5])*y+p[6])*y+p[7])*y+p[8])*y+p[9])*y+p[10])*y+p[11])*y+p[12])*y+p[13])*y+p[14])*y+p[15])*y+p[16])

#define POLY2_1      0
#define POLY2_3      (POLY2_1     + 45 )
#define POLY2_5      (POLY2_3     + 45 )
#define POLY2_10     (POLY2_5     + 45 )
#define POLY2_15     (POLY2_10    + 45 )
#define POLY2_33     (POLY2_15    + 45 )
#define POLY2_40     (POLY2_33    + 45 )
#define POLY2_RBASE  (POLY2_40    + 8  )
#define POLY2_WBASE  (POLY2_RBASE + 2  )
#define POLY3_1      (POLY2_WBASE + 2  )
#define POLY3_3      (POLY3_1     + 56 )
#define POLY3_5      (POLY3_3     + 56 )
#define POLY3_10     (POLY3_5     + 56 )
#define POLY3_15     (POLY3_10    + 56 )
#define POLY3_20     (POLY3_15    + 56 )
#define POLY3_33     (POLY3_20    + 56 )
#define POLY3_47     (POLY3_33    + 56 )
#define POLY3_RBASE  (POLY3_47    + 24 )
#define POLY3_WBASE  (POLY3_RBASE + 3  )
#define POLY4_1      (POLY3_WBASE + 3  )
#define POLY4_5      (POLY4_1     + 144)
#define POLY4_10     (POLY4_5     + 144)
#define POLY4_15     (POLY4_10    + 144)
#define POLY4_20     (POLY4_15    + 144)
#define POLY4_25     (POLY4_20    + 144)
#define POLY4_35     (POLY4_25    + 144)
#define POLY4_53     (POLY4_35    + 144)
#define POLY4_RBASE  (POLY4_53    + 144)
#define POLY4_WBASE  (POLY4_RBASE + 4  )
#define POLY5_1      (POLY4_WBASE + 4  )
#define POLY5_5      (POLY5_1     + 170)
#define POLY5_10     (POLY5_5     + 170)
#define POLY5_15     (POLY5_10    + 170)
#define POLY5_20     (POLY5_15    + 170)
#define POLY5_25     (POLY5_20    + 170)
#define POLY5_40     (POLY5_25    + 170)
#define POLY5_59     (POLY5_40    + 170)
#define POLY5_RBASE  (POLY5_59    + 170)
#define POLY5_WBASE  (POLY5_RBASE + 5  )

__device__
constexpr double FITTING_DATA[] = {
    // static double POLY2_1[] = {
    // FT0
    +0, +0, +0, +0, +0, +0, -2.35234358048491E-09, +2.49173650389842E-08,
    -4.558315364581E-08, -2.447252174587E-06, +4.743292959463E-05,
    -5.33184749432408E-04, +4.44654947116579E-03, -2.90430236084697E-02,
    +1.30693606237085E-01,
    // FT1
    +0, +0, +0, +0, +0, +0, -2.47404902329170E-08, +2.36809910635906E-07,
    +1.835367736310E-06, -2.066168802076E-05, -1.345693393936E-04,
    -5.88154362858038E-05, +5.32735082098139E-02, -6.37623643056745E-01,
    +2.86930639376289E+00,
    // WT0
    +0, +0, +0, +0, +0, -8.36313918003957E-08, +1.21222603512827E-06,
    -1.15662609053481E-05, +9.25197374512647E-05, -6.40994113129432E-04,
    +3.78787044215009E-03, -1.85185172458485E-02, +7.14285713298222E-02,
    -1.99999999997023E-01, +3.33333333333318E-01,
    //};
    // static double POLY2_3[] = {
    // FT0
    +0, +0, +0, +0, -6.36859636616415E-12, +8.47417064776270E-11,
    -5.152207846962E-10, -3.846389873308E-10, +8.472253388380E-08,
    -1.85306035634293E-06, +2.47191693238413E-05, -2.49018321709815E-04,
    +2.19173220020161E-03, -1.63329339286794E-02, +8.68085688285261E-02,
    // FT1
    +0, +0, +0, +0, +1.45331350488343E-10, +2.07111465297976E-09,
    -1.878920917404E-08, -1.725838516261E-07, +2.247389642339E-06,
    +9.76783813082564E-06, -1.93160765581969E-04, -1.58064140671893E-03,
    +4.85928174507904E-02, -4.30761584997596E-01, +1.80400974537950E+00,
    // WT0
    +0, +0, +0, -1.61702782425558E-10, +1.96215250865776E-09,
    -2.14234468198419E-08, +2.17216556336318E-07, -1.98850171329371E-06,
    +1.62429321438911E-05, -1.16740298039895E-04, +7.24888732052332E-04,
    -3.79490003707156E-03, +1.61723488664661E-02, -5.29428148329736E-02,
    +1.15702180856167E-01,
    //};
    // static double POLY2_5[] = {
    // FT0
    +0, +0, +0, +0, +0, -4.11560117487296E-12, +7.10910223886747E-11,
    -1.73508862390291E-09, +5.93066856324744E-08, -9.76085576741771E-07,
    +1.08484384385679E-05, -1.12608004981982E-04, +1.16210907653515E-03,
    -9.89572595720351E-03, +6.12589701086408E-02,
    // FT1
    +0, +0, +0, +0, -1.80555625241001E-10, +5.44072475994123E-10,
    +1.603498045240E-08, -1.497986283037E-07, -7.017002532106E-07,
    +1.85882653064034E-05, -2.04685420150802E-05, -2.49327728643089E-03,
    +3.56550690684281E-02, -2.60417417692375E-01, +1.12155283108289E+00,
    // WT0
    +0, +0, +0, -2.62453564772299E-11, +3.24031041623823E-10,
    -3.614965656163E-09, +3.760256799971E-08, -3.553558319675E-07,
    +3.022556449731E-06, -2.290098979647E-05, +1.526537461148E-04,
    -8.81947375894379E-04, +4.33207949514611E-03, -1.75257821619926E-02,
    +5.28406320615584E-02,
    //};
    // static double POLY2_10[] = {
    // FT0
    -1.43632730148572E-16, +2.38198922570405E-16, +1.358319618800E-14,
    -7.064522786879E-14, -7.719300212748E-13, +7.802544789997E-12,
    +6.628721099436E-11, -1.775564159743E-09, +1.713828823990E-08,
    -1.497500187053E-07, +2.283485114279E-06, -3.76953869614706E-05,
    +4.74791204651451E-04, -4.60448960876139E-03, +3.72458587837249E-02,
    // FT1
    +0, +2.48791622798900E-14, -1.36113510175724E-13, -2.224334349799E-12,
    +4.190559455515E-11, -2.222722579924E-10, -2.624183464275E-09,
    +6.128153450169E-08, -4.383376014528E-07, -2.49952200232910E-06,
    +1.03236647888320E-04, -1.44614664924989E-03, +1.35094294917224E-02,
    -9.53478510453887E-02, +5.44765245686790E-01,
    // WT0
    +0, +0, +0, +0, +0, +0, +0, +0, +4.6897511375022E-01, -6.9955602298985E-01,
    +5.3689283271887E-01, -3.2883030418398E-01, +2.4645596956002E-01,
    -4.9984072848436E-01, -3.1501078774085E-06,
    //};
    // static double POLY2_15[] = {
    // FT0
    +0, +0, +0, +0, +0, +0, -1.01041157064226E-05, +1.19483054115173E-03,
    -6.73760231824074E-02, +1.25705571069895E+00, -2.38570496490846E+01,
    +2.64536689959503E+02, -1.70807677109425E+03, +5.91005939591842E+03,
    -8.57609422987199E+03,
    // FT1
    +0, +0, +0, +0, +0, +0, +0, +3.39024225137123E-04, -9.34976436343509E-02,
    -4.22216483306320E+00, +8.00839033297501E+00, -1.56184800325063E+02,
    +3.39891508992661E+02, -1.04999071905664E+03, -2.08457050986847E+03,
    // WT0
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, -2.1916512131607E-05,
    -4.9893752514047E-01, +2.2991849164985E-01, -1.8784686463512E-01, +0,
    //};
    // static double POLY2_33[] = {
    // RT0
    +0, +0, +0, +0, +0, +0, +0, +0, -1.14906395546354E-06,
    +1.76003409708332E-04, -1.71984023644904E-02, -1.37292644149838E-01,
    -2.31080873898939E-02, +9.21005186542857E+00, -4.75742064274859E+01,
    // RT1
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +3.64921633404158E-04,
    -9.71850973831558E-02, -4.02886174850252E+00, +2.98011277766958E+00,
    -8.66891724287962E+01, -1.35831002139173E+02,
    // WT0
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, -6.0156581186481E-05,
    -4.9695241464490E-01, +1.9623264149430E-01,
    //};
    // static double POLY2_40[] = {
    // RT0
    -8.78947307498880E-01, +1.09243702330261E+01,
    // RT1
    -9.28903924275977E+00, +8.10642367843811E+01,
    // WT0
    -4.46857389308400E+00, +7.79250653461045E+01,
    // WT1
    +4.46857389308400E+00, -7.79250653461045E+01,
    //};

    // static double POLY2_RBASE[] = {
    2.75255128608411E-01, 2.72474487139158E+00,
    //};
    // static double POLY2_WBASE[] = {
    9.08248290463863E-01, 9.17517095361369E-02,
    //};

    // static double POLY3_1[] = {
    // RT0
    +0, +0, +0, +0, +0, +0, -5.10186691538870E-10, +2.40134415703450E-08,
    -5.01081057744427E-07, +7.58291285499256E-06, -9.55085533670919E-05,
    +1.02893039315878E-03, -9.28875764374337E-03, +6.03769246832810E-02,
    // RT1
    +0, +0, +0, +0, +0, +0, -1.29646524960555E-08, +7.74602292865683E-08,
    +1.56022811158727E-06, -1.58051990661661E-05, -3.30447806384059E-04,
    +9.74266885190267E-03, -1.19511285526388E-01, +7.76823355931033E-01,
    // RT2
    +0, +0, +0, +0, +0, +0, -9.28536484109606E-09, -3.02786290067014E-07,
    -2.50734477064200E-06, -7.32728109752881E-06, +2.44217481700129E-04,
    +4.94758452357327E-02, -1.02504611065774E+00, +6.66279971938553E+00,
    // F2
    +0, +0, +0., +0., -7.60911486098850E-08, +1.09552870123182E-06,
    -1.03463270693454E-05, +8.16324851790106E-05, -5.55526624875562E-04,
    +3.20512054753924E-03, -1.51515139838540E-02, +5.55555554649585E-02,
    -1.42857142854412E-01, +1.99999999999986E-01,
    //};
    // static double POLY3_3[] = {
    // RT0
    +0, +0, +0, +0, +1.44687969563318E-12, +4.85300143926755E-12,
    -6.55098264095516E-10, +1.56592951656828E-08, -2.60122498274734E-07,
    +3.86118485517386E-06, -5.13430986707889E-05, +6.03194524398109E-04,
    -6.11219349825090E-03, +4.52578254679079E-02,
    // RT1
    +0, +0, +0, +0, +0, +6.95964248788138E-10, -5.35281831445517E-09,
    -6.745205954533E-08, +1.502366784525E-06, +9.923326947376E-07,
    -3.89147469249594E-04, +7.51549330892401E-03, -8.48778120363400E-02,
    +5.73928229597613E-01,
    // RT2
    +0, +0, +0, +0, -2.81496588401439E-10, +3.61058041895031E-09,
    +4.53631789436255E-08, -1.40971837780847E-07, -6.05865557561067E-06,
    -5.15964042227127E-05, +3.34761560498171E-05, +5.04871005319119E-02,
    -8.24708946991557E-01, +4.81234667357205E+00,
    // F2
    +0, +0, -1.48044231072140E-10, +1.78157031325097E-09, -1.92514145088973E-08,
    +1.92804632038796E-07, -1.73806555021045E-06, +1.39195169625425E-05,
    -9.74574633246452E-05, +5.83701488646511E-04, -2.89955494844975E-03,
    +1.13847001113810E-02, -3.23446977320647E-02, +5.29428148329709E-02,
    //};
    // static double POLY3_5[] = {
    // RT0
    +0, +0, +0, +0, +0, +1.44265709189601E-11, -4.66622033006074E-10,
    +7.649155832025E-09, -1.229940017368E-07, +2.026002142457E-06,
    -2.87048671521677E-05, +3.70326938096287E-04, -4.21006346373634E-03,
    +3.50898470729044E-02,
    // RT1
    +0, +0, +0, +0, -2.65526039155651E-11, +1.97549041402552E-10,
    +2.15971131403034E-09, -7.95045680685193E-08, +5.15021914287057E-07,
    +1.11788717230514E-05, -3.33739312603632E-04, +5.30601428208358E-03,
    -5.93483267268959E-02, +4.31180523260239E-01,
    // RT2
    +0, +0, +0, +0, -3.92833750584041E-10, -4.16423229782280E-09,
    +4.42413039572867E-08, +6.40574545989551E-07, -3.05512456576552E-06,
    -1.05296443527943E-04, -6.14120969315617E-04, +4.89665802767005E-02,
    -6.24498381002855E-01, +3.36412312243724E+00,
    // F2
    +0, +0, -2.36788772599074E-11, +2.89147476459092E-10, -3.18111322308846E-09,
    +3.25336816562485E-08, -3.00873821471489E-07, +2.48749160874431E-06,
    -1.81353179793672E-05, +1.14504948737066E-04, -6.10614987696677E-04,
    +2.64584212770942E-03, -8.66415899015349E-03, +1.75257821619922E-02,
    //};
    // static double POLY3_10[] = {
    // RT0
    +0, +5.74429401360115E-16, +7.11884203790984E-16, -6.736701449826E-14,
    -6.264613873998E-13, +1.315418927040E-11, -4.23879635610964E-11,
    +1.39032379769474E-09, -4.65449552856856E-08, +7.34609900170759E-07,
    -1.08656008854077E-05, +1.77930381549953E-04, -2.39864911618015E-03,
    +2.39112249488821E-02,
    // RT1
    +0, +1.13464096209120E-14, +6.99375313934242E-15, -8.595618132088E-13,
    -5.293620408757E-12, -2.492175211635E-11, +2.73681574882729E-09,
    -1.06656985608482E-08, -4.40252529648056E-07, +9.68100917793911E-06,
    -1.68211091755327E-04, +2.69443611274173E-03, -3.23845035189063E-02,
    +2.75969447451882E-01,
    // RT2
    +6.66339416996191E-15, +1.84955640200794E-13, -1.985141104444E-12,
    -2.309293727603E-11, +3.917984522103E-10, +1.663165279876E-09,
    -6.205591993923E-08, +8.769581622041E-09, +8.97224398620038E-06,
    -3.14232666170796E-05, -1.83917335649633E-03, +3.51246831672571E-02,
    -3.22335051270860E-01, +1.73582831755430E+00,
    // WT0
    0, 0, 0, 0, 0, 0, 0, +4.6897511375022E-01, -6.9955602298985E-01,
    +5.3689283271887E-01, -3.2883030418398E-01, +2.4645596956002E-01,
    -4.9984072848436E-01, -3.1501078774085E-06,
    //};
    // static double POLY3_15[] = {
    // RT0
    +0, +4.42133001283090E-16, -2.77189767070441E-15, -4.084026087887E-14,
    +5.379885121517E-13, +1.882093066702E-12, -8.67286219861085E-11,
    +7.11372337079797E-10, -3.55578027040563E-09, +1.29454702851936E-07,
    -4.14222202791434E-06, +8.04427643593792E-05, -1.18587782909876E-03,
    +1.53435577063174E-02,
    // RT1
    +0, +6.85146742119357E-15, -1.08257654410279E-14, -8.579165965128E-13,
    +6.642452485783E-12, +4.798806828724E-11, -1.13413908163831E-09,
    +7.08558457182751E-09, -5.59678576054633E-08, +2.51020389884249E-06,
    -6.63678914608681E-05, +1.11888323089714E-03, -1.45361636398178E-02,
    +1.65077877454402E-01,
    // RT2
    +3.20622388697743E-15, -2.73458804864628E-14, -3.157134329361E-13,
    +8.654129268056E-12, -5.625235879301E-11, -7.718080513708E-10,
    +2.064664199164E-08, -1.567725007761E-07, -1.57938204115055E-06,
    +6.27436306915967E-05, -1.01308723606946E-03, +1.13901881430697E-02,
    -1.01449652899450E-01, +7.77203937334739E-01,
    // WT0
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.8784686463512E-01, +2.2991849164985E-01,
    -4.9893752514047E-01, -2.1916512131607E-05,
    //};

    // static double POLY3_20[] = {
    // RT0
    +0, +0, +0, +0, -2.43270989903742E-06, +3.57901398988359E-04,
    -2.34112415981143E-02, +7.81425144913975E-01, -1.73209218219175E+01,
    +2.43517435690398E+02, -2.07970687843258E+03, +9.82441363463929E+03,
    -1.97611541576986E+04, +0,
    // RT1
    +0, +0, +0, +0, +0, -2.62627010965435E-04, +3.49187925428138E-02,
    -3.09337618731880E+00, +1.07037141010778E+02, -2.36659637247087E+03,
    +3.35202872835409E+04, -2.91532335433779E+05, +1.41129505262758E+06,
    -2.91669113681020E+06,
    // RT2
    +0, +0, +0, +0, +0, +9.31856404738601E-05, -2.87029400759565E-02,
    -7.83503697918455E-01, -1.84338896480695E+01, +4.04996712650414E+02,
    -6.88145821789955E+03, +5.11498390849158E+04, -1.89829509315154E+05, +0,
    // WT0
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6.0156581186481E-05, -4.9695241464490E-01,
    +1.9623264149430E-01, +0,
    //};
    // static double POLY3_33[] = {
    // RT0
    +0, +0, +0, +0, +0, +0, +0, -4.97561537069643E-04, -5.00929599665316E-02,
    +1.31099142238996E+00, -1.88336409225481E+01, +1.64931462413877E+02,
    -6.60344754467191E+02, +0,
    // RT1
    +0, +0, +0, +0, +0, +0, +0, -4.48218898474906E-03, -5.17373211334924E-01,
    +1.13691058739678E+01, -1.65426392885291E+02, +1.52231757709236E+03,
    -6.30909125686731E+03, +0,
    // RT2
    +0, +0, +0, +0, +0, +0, +0, -1.38368602394293E-02, -1.77293428863008E+00,
    +1.73639054044562E+01, -3.57615122086961E+02, +2.69831813951849E+03,
    -1.45734701095912E+04, +0,
    // WT0
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, -6.0156581186481E-05,
    -4.9695241464490E-01, +1.9623264149430E-01,
    //};
    // static double POLY3_47[] = {
    // RT0
    +0, -7.39058467995275E+00, +3.21318352526305E+02, -3.99433696473658E+03,
    // RT1
    +0, -7.38726243906513E+01, +3.13569966333873E+03, -3.86862867311321E+04,
    // RT2
    +0, -2.63750565461336E+02, +1.04412168692352E+04, -1.28094577915394E+05,
    // WT0
    -1.52258947224714E-01, -5.32006425493546E+01, +2.72682910653471E+03,
    -3.64015510486804E+04,
    // WT1
    +0, +6.15072615497811E+01, -2.91980647450269E+03, +3.80794303087338E+04,
    // WT2
    +1.52258947224714E-01, -8.30661900042651E+00, +1.92977367967984E+02,
    -1.67787926005344E+03,
    //};

    // static double POLY3_RBASE[] = {
    1.90163509193487E-01, 1.78449274854325E+00, 5.52534374226326E+00,
    //};
    // static double POLY3_WBASE[] = {
    8.17656939112059E-01, 1.77231492083829E-01, 5.11156880411248E-03,
    //};

    // static double POLY4_1[] = {
    // RT0
    +0, +0, +0, +0, +0, +0, +0, +0, -1.95309614628539E-10,
    +5.19765728707592E-09, -1.01756452250573E-07, +1.72365935872131E-06,
    -2.61203523522184E-05, +3.52921308769880E-04, -4.09645850658433E-03,
    +3.48198973061469E-02,
    // RT1
    +0, +0, +0, +0, +0, +0, +0, +0, +0, -1.89554881382342E-08,
    +3.07583114342365E-07, +1.270981734393E-06, -1.417298563884E-04,
    +3.226979163176E-03, -4.48902570678178E-02, +3.81567185080039E-01,
    // RT2
    +0, +0, +0, +0, +0, +0, +0, +0, +1.77280535300416E-09,
    +3.36524958870615E-08, -2.58341529013893E-07, -1.13644895662320E-05,
    -7.91549618884063E-05, +1.03825827346828E-02, -2.04389090525137E-01,
    +1.73730726945889E+00,
    // RT3
    +0, +0, +0, +0, +0, +0, +0, +0, +0, -5.61188882415248E-08,
    -2.49480733072460E-07, +3.428685057114E-06, +1.679007454539E-04,
    +4.722855585715E-02, -1.39368301737828E+00, +1.18463056481543E+01,
    // WT0
    +0, +0, +0, +0, +0, -4.99660550769508E-09, +1.17744644867760E-07,
    -1.40864254947449E-06, +1.31591707798218E-05, -1.06607881641102E-04,
    +7.55222585086693E-04, -4.60273537616210E-03, +2.35152542049921E-02,
    -9.69345107844124E-02, +3.01948902760539E-01, -6.37316216621631E-01,
    // WT1
    +0, +0, +0, +0, +0, +0, -4.11720483772634E-09, +6.54963481852134E-08,
    -7.20045285129626E-07, +6.93779646721723E-06, -6.05367572016373E-05,
    +4.74241566251899E-04, -3.26956188125316E-03, +1.91883866626681E-02,
    -8.98046242565811E-02, +3.13706645877886E-01,
    // WT2
    +0, +0, +0, +0, +0, +0, -3.41688436990215E-08, +5.07238960340773E-07,
    -5.01675628408220E-06, +4.20363420922845E-05, -3.08040221166823E-04,
    +1.94431864731239E-03, -1.02477820460278E-02, +4.28670143840073E-02,
    -1.29314370962569E-01, +2.22381034453369E-01,
    // WT3
    +0, +0, +0, +0, +0, +4.99660550769508E-09, -7.94585963310120E-08,
    +8.359072409485E-07, -7.422369210610E-06, +5.763374308160E-05,
    -3.86645606718233E-04, +2.18417516259781E-03, -9.99791027771119E-03,
    +3.48791097377370E-02, -8.28299075413889E-02, +1.01228536290376E-01,
    // W0
    +0, +0, +0, +0, +0, +0, +0, +0, -1.14649303201279E-08,
    +1.88015570196787E-07, -2.33305875372323E-06, +2.68880044371597E-05,
    -2.94268428977387E-04, +3.06548909776613E-03, -3.13844305680096E-02,
    +3.62683783378335E-01,
    //};
    // static double POLY4_5[] = {
    // RT0
    +0, +0, +0, +0, +0, -1.48570633747284E-15, -1.33273068108777E-13,
    +4.068543696670E-12, -9.163164161821E-11, +2.046819017845E-09,
    -4.03076426299031E-08, +7.29407420660149E-07, -1.23118059980833E-05,
    +1.88796581246938E-04, -2.53262912046853E-03, +2.51198234505021E-02,
    // RT1
    +0, +0, +0, +0, +0, +1.35830583483312E-13, -2.29772605964836E-12,
    -3.821500128045E-12, +6.844424214735E-10, -1.048063352259E-08,
    +1.50083186233363E-08, +3.48848942324454E-06, -1.08694174399193E-04,
    +2.08048885251999E-03, -2.91205805373793E-02, +2.72276489515713E-01,
    // RT2
    +0, +0, +0, +0, +0, +5.02799392850289E-13, +1.07461812944084E-11,
    -1.482277886411E-10, -2.153585661215E-09, +3.654087802817E-08,
    +5.15929575830120E-07, -9.52388379435709E-06, -2.16552440036426E-04,
    +9.03551469568320E-03, -1.45505469175613E-01, +1.21449092319186E+00,
    // RT3
    +0, +0, +0, +0, +0, -1.08510370291979E-12, +6.41492397277798E-11,
    +7.542387436125E-10, -2.213111836647E-09, -1.448228963549E-07,
    -1.95670833237101E-06, -1.07481314670844E-05, +1.49335941252765E-04,
    +4.87791531990593E-02, -1.10559909038653E+00, +8.09502028611780E+00,
    // WT0
    +9.74835552342257E-16, -2.48538311206712E-14, +3.80175208104042E-13,
    -5.31833622965418E-12, +7.07792106807470E-11, -8.75322027483900E-10,
    +9.97591593456225E-09, -1.04174350690620E-07, +9.89713396831603E-07,
    -8.48422219915122E-06, +6.50264490135502E-05, -4.41060022895452E-04,
    +2.61662877566309E-03, -1.33773518464271E-02, +5.70005791272365E-02,
    -2.14444908795409E-01,
    // WT1
    +0, +0, -1.46345073267549E-14, +2.25644205432182E-13, -3.116258693847E-12,
    +4.321908756610E-11, -5.673270062669E-10, +7.006295962960E-09,
    -8.120186517000E-08, +8.775294645770E-07, -8.77829235749024E-06,
    +8.04372147732379E-05, -6.64149238804153E-04, +4.81181506827225E-03,
    -2.88982669486183E-02, +1.56247249979288E-01,
    // WT2
    +0, +9.06812118895365E-15, -1.40541322766087E-13, +1.919270015269E-12,
    -2.605135739010E-11, +3.299685839012E-10, -3.86354139348735E-09,
    +4.16265847927498E-08, -4.09462835471470E-07, +3.64018881086111E-06,
    -2.88665153269386E-05, +2.00515819789028E-04, -1.18791896897934E-03,
    +5.75223633388589E-03, -2.09400418772687E-02, +4.85368861938873E-02,
    // WT3
    -9.74835552342257E-16, +1.57857099317175E-14, -2.249993780112E-13,
    +3.173422008953E-12, -4.161159459680E-11, +5.021343560166E-10,
    -5.545047534808E-09, +5.554146993491E-08, -4.99048696190133E-07,
    +3.96650392371311E-06, -2.73816413291214E-05, +1.60106988333186E-04,
    -7.64560567879592E-04, +2.81330044426892E-03, -7.16227030134947E-03,
    +9.66077262223353E-03,
    // W0
    +0, +0, +0, +0, -4.65801912689961E-14, +7.58669507106800E-13,
    -1.186387548048E-11, +1.862334710665E-10, -2.799399389539E-09,
    +4.148972684255E-08, -5.933568079600E-07, +8.168349266115E-06,
    -1.08989176177409E-04, +1.41357961729531E-03, -1.87588361833659E-02,
    +2.89898651436026E-01,
    //};
    // static double POLY4_10[] = {
    // RT0
    +0, +0, +0, +0, +0, +4.64217329776215E-15, -6.27892383644164E-15,
    +3.462236347446E-13, -2.927229355350E-11, +5.090355371676E-10,
    -9.97272656345253E-09, +2.37835295639281E-07, -4.60301761310921E-06,
    +8.42824204233222E-05, -1.37983082233081E-03, +1.66630865869375E-02,
    // RT1
    +0, +0, +0, +0, +0, +2.93981127919047E-14, +8.47635639065744E-13,
    -1.446314544774E-11, -6.149155555753E-12, +8.484275604612E-10,
    -6.10898827887652E-08, +2.39156093611106E-06, -5.35837089462592E-05,
    +1.00967602595557E-03, -1.57769317127372E-02, +1.74853819464285E-01,
    // RT2
    +0, +0, +0, +0, +2.93523563363000E-14, -6.40041776667020E-14,
    -2.695740446312E-12, +1.027082960169E-10, -5.822038656780E-10,
    -3.159991002539E-08, +4.327249251331E-07, +4.856768455119E-06,
    -2.54617989427762E-04, +5.54843378106589E-03, -7.95013029486684E-02,
    +7.20206142703162E-01,
    // RT3
    +0, +0, +0, -1.62212382394553E-14, +7.68943641360593E-13,
    +5.764015756615E-12, -1.380635298784E-10, -1.476849808675E-09,
    +1.84347052385605E-08, +3.34382940759405E-07, -1.39428366421645E-06,
    -7.50249313713996E-05, -6.26495899187507E-04, +4.69716410901162E-02,
    -6.66871297428209E-01, +4.11207530217806E+00,
    // WT0
    +1.55714130075679E-17, -4.21936181233168E-16, +6.66897826457315E-15,
    -9.64933375300033E-14, +1.35417272409284E-12, -1.78572743737070E-11,
    +2.20838091742164E-10, -2.55376229535002E-09, +2.74910796127749E-08,
    -2.77732805745392E-07, +2.63953382801440E-06, -2.34636087186406E-05,
    +1.97730107640102E-04, -1.56284259858747E-03, +1.09761084985307E-02,
    -9.68734616485846E-02,
    // WT1
    +0, +0, -3.57248951192047E-16, +6.25708409149331E-15, -9.657033089714E-14,
    +1.507864898748E-12, -2.332522256110E-11, +3.428545616603E-10,
    -4.698730937661E-09, +6.219977635130E-08, -7.83008889613661E-07,
    +9.08621687041567E-06, -9.86368311253873E-05, +9.69632496710088E-04,
    -8.14594214284187E-03, +8.50218447733457E-02,
    // WT2
    +0, +1.64742458534277E-16, -2.68512265928410E-15, +3.788890667676E-14,
    -5.508918529823E-13, +7.555896810069E-12, -9.69039768312637E-11,
    +1.16034263529672E-09, -1.28771698573873E-08, +1.31949431805798E-07,
    -1.23673915616005E-06, +1.04189803544936E-05, -7.79566003744742E-05,
    +5.03162624754434E-04, -2.55138844587555E-03, +1.13250730954014E-02,
    // WT3
    -1.55714130075679E-17, +2.57193722698891E-16, -3.626606654097E-15,
    +5.234734676175E-14, -7.067105402134E-13, +8.793512664890E-12,
    -1.006088923498E-10, +1.050565098393E-09, -9.91517881772662E-09,
    +8.35835975882941E-08, -6.19785782240693E-07, +3.95841149373135E-06,
    -2.11366761402403E-05, +9.00474771229507E-05, -2.78777909813289E-04,
    +5.26543779837487E-04,
    // W0
    +0, +0, +0, +0, -1.65995045235997E-15, +6.91838935879598E-14,
    -9.131223418888E-13, +1.403341829454E-11, -3.672235069444E-10,
    +6.366962546990E-09, -1.039220021671E-07, +1.959098751715E-06,
    -3.33474893152939E-05, +5.72164211151013E-04, -1.05583210553392E-02,
    +2.26696066029591E-01,
    //};
    // static double POLY4_15[] = {
    // RT0
    +0, +0, +0, +4.94869622744119E-17, +8.03568805739160E-16,
    -5.599125915431E-15, -1.378685560217E-13, +7.006511663249E-13,
    +1.30391406991118E-11, +8.06987313467541E-11, -5.20644072732933E-09,
    +7.72794187755457E-08, -1.61512612564194E-06, +4.15083811185831E-05,
    -7.87855975560199E-04, +1.14189319050009E-02,
    // RT1
    +0, +0, +0, +4.89224285522336E-16, +1.06390248099712E-14,
    -5.446260182933E-14, -1.613630106295E-12, +3.910179118937E-12,
    +1.90712434258806E-10, +8.78470199094761E-10, -5.97332993206797E-08,
    +9.25750831481589E-07, -2.02362185197088E-05, +4.92341968336776E-04,
    -8.68438439874703E-03, +1.15825965127958E-01,
    // RT2
    +0, +0, +0, +0, +6.12419396208408E-14, +1.12328861406073E-13,
    -9.051094103059E-12, -4.781797525341E-11, +1.660828868694E-09,
    +4.499058798868E-10, -2.519549641933E-07, +4.977444040180E-06,
    -1.25858350034589E-04, +2.70279176970044E-03, -3.99327850801083E-02,
    +4.33467200855434E-01,
    // RT3
    +0, +0, +0, +4.63414725924048E-14, -4.72757262693062E-14,
    -1.001926833832E-11, +6.074107718414E-11, +1.576976911942E-09,
    -2.01186401974027E-08, -1.84530195217118E-07, +5.02333087806827E-06,
    +9.66961790843006E-06, -1.58522208889528E-03, +2.80539673938339E-02,
    -2.78953904330072E-01, +1.82835655238235E+00,
    // WT0
    +0, -2.90401781000996E-18, +8.82958828557731E-17, -1.22174600009424E-15,
    +2.66467047516641E-14, -4.11729113408554E-13, +4.55280965407696E-12,
    -6.58987745677613E-11, +1.08578149050608E-09, -1.40411853640192E-08,
    +1.63991917855494E-07, -2.21538549551131E-06, +2.96212765004176E-05,
    -3.25378665875111E-04, +3.42937243191073E-03, -6.56477809845696E-02,
    // WT1
    +0, +0, +0, +0, -6.22272689880615E-15, +1.04126809657554E-13,
    -6.842418230913E-13, +1.576841731919E-11, -4.203948834175E-10,
    +6.287255934781E-09, -8.307159819228E-08, +1.356478091922E-06,
    -2.08065576105639E-05, +2.52396730332340E-04, -2.94484050194539E-03,
    +6.01396183129168E-02,
    // WT2
    +0, +0, -4.19569145459480E-17, +5.94344180261644E-16, -1.148797566469E-14,
    +1.881303962576E-13, -2.413554618391E-12, +3.372127423047E-11,
    -4.933988617784E-10, +6.116545396281E-09, -6.69965691739299E-08,
    +7.52380085447161E-07, -8.08708393262321E-06, +6.88603417296672E-05,
    -4.67067112993427E-04, +5.42313365864597E-03,
    // WT3
    +0, +2.90401781000996E-18, -4.63389683098251E-17, +6.274018198326E-16,
    -8.936002188168E-15, +1.194719074934E-13, -1.45501321259466E-12,
    +1.64090830181013E-11, -1.71987745310181E-10, +1.63738403295718E-09,
    -1.39237504892842E-08, +1.06527318142151E-07, -7.27634957230524E-07,
    +4.12159381310339E-06, -1.74648169719173E-05, +8.50290130067818E-05,
    // W0
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, -1.8784686463512e-01,
    +2.2991849164985e-01, -4.9893752514047e-01, -2.1916512131607e-05,
    //};
    // static double POLY4_20[] = {
    // RT0
    +0, +0, +0, +4.36701759531398E-17, -1.12860600219889E-16,
    -6.149849164164E-15, +5.820231579541E-14, +4.396602872143E-13,
    -1.24330365320172E-11, +6.71083474044549E-11, +2.43865205376067E-10,
    +1.67559587099969E-08, -9.32738632357572E-07, +2.39030487004977E-05,
    -4.68648206591515E-04, +8.34977776583956E-03,
    // RT1
    +0, +0, +0, +4.98913142288158E-16, -2.60732537093612E-16,
    -7.775156445127E-14, +5.766105220086E-13, +6.432696729600E-12,
    -1.39571683725792E-10, +5.95451479522191E-10, +2.42471442836205E-09,
    +2.47485710143120E-07, -1.14710398652091E-05, +2.71252453754519E-04,
    -4.96812745851408E-03, +8.26020602026780E-02,
    // RT2
    +0, +0, +0, +1.91498302509009E-15, +1.48840394311115E-14,
    -4.316925145767E-13, +1.186495793471E-12, +4.615806713055E-11,
    -5.54336148667141E-10, +3.48789978951367E-10, -2.79188977451042E-09,
    +2.09563208958551E-06, -6.76512715080324E-05, +1.32129867629062E-03,
    -2.05062147771513E-02, +2.88068671894324E-01,
    // RT3
    +0, +0, +0, -5.43697691672942E-15, -1.12483395714468E-13,
    +2.826607936174E-12, -1.266734493280E-11, -4.258722866437E-10,
    +9.45486578503261E-09, -5.86635622821309E-08, -1.28835028104639E-06,
    +4.41413815691885E-05, -7.61738385590776E-04, +9.66090902985550E-03,
    -1.01410568057649E-01, +9.54714798156712E-01,
    // WT0
    +0, +0, +7.56882223582704E-19, +2.34415744029184E-16, -1.31962770838549E-15,
    -4.15385242584840E-14, +7.36598321622260E-13, -4.11774889911750E-12,
    +8.22639798319305E-12, -8.99776410856736E-10, +3.05045593473329E-08,
    -5.36499686078243E-07, +6.91814626987763E-06, -8.96845906637426E-05,
    +1.62660177452937E-03, -5.39592103544987E-02,
    // WT1
    +0, +0, +0, -1.86506057729700E-16, +1.16661114435809E-15,
    +2.563712856363E-14, -4.498350984631E-13, +1.765194089338E-12,
    +9.04483676345625E-12, +4.98930345609785E-10, -2.11964170928181E-08,
    +3.98295476005614E-07, -5.49390160829409E-06, +7.74065155353262E-05,
    -1.48201933009105E-03, +4.97836392625268E-02,
    // WT2
    +0, +0, +0, -5.54451040921657E-17, +2.68748367250999E-16,
    +1.349020069254E-14, -2.507452792892E-13, +1.944339743818E-12,
    -1.29816917658823E-11, +3.49977768819641E-10, -8.67270669346398E-09,
    +1.31381116840118E-07, -1.36790720600822E-06, +1.19210697673160E-05,
    -1.42181943986587E-04, +4.12615396191829E-03,
    // WT3
    +0, +0, -7.56882223582704E-19, +7.53541779268175E-18, -1.157318032236E-16,
    +2.411195002314E-15, -3.601794386996E-14, +4.082150659615E-13,
    -4.289542980767E-12, +5.086829642731E-11, -6.35435561050807E-10,
    +6.82309323251123E-09, -5.63374555753167E-08, +3.57005361100431E-07,
    -2.40050045173721E-06, +4.94171300536397E-05,
    // W0
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1.9623264149430E-01,
    -4.9695241464490E-01, -6.0156581186481E-05,
    //};
    // static double POLY4_25[] = {
    // RT0
    +0, +0, +0, +0, +0, +0, -4.45711399441838E-05, +1.27267770241379E-03,
    -2.36954961381262E-01, +1.54330657903756E+01, -5.22799159267808E+02,
    +1.05951216669313E+04, -1.29194382386499E+05, +8.72975373557709E+05,
    -2.51177235556236E+06, +0,
    // RT1
    +0, +0, +0, +0, +0, +0, +0, -7.85617372254488E-02, +6.35653573484868E+00,
    -3.38296938763990E+02, +1.25120495802096E+04, -3.16847570511637E+05,
    +5.38614211391604E+06, -5.87119005093822E+07, +3.70104713293016E+08,
    -1.02427466127427E+09,
    // RT2
    +0, +0, +0, +0, +0, +0, +0, -2.37900485051067E-01, +1.84122184400896E+01,
    -1.00200731304146E+03, +3.75151841595736E+04, -9.50626663390130E+05,
    +1.60419390230055E+07, -1.72465289687396E+08, +1.06625915044526E+09,
    -2.88139014651985E+09,
    // RT3
    +0, +0, +0, +0, +0, +0, -6.00691586407385E-04, -3.64479545338439E-01,
    +1.57496131755179E+01, -6.54944248734901E+02, +1.70830039597097E+04,
    -2.90517939780207E+05, +2.96817940164703E+06, -1.64944522586065E+07,
    +3.49059698304732E+07, +0,
    // WT0
    +0, +0, +0, +0, +0, -2.33766206773151E-07, -9.28080413509453E-04,
    +4.10436429419876E-02, -2.37362221036171E+00, +1.15359027018623E+02,
    -3.56391369065139E+03, +6.79419863399775E+04, -7.58175598437090E+05,
    +4.10741083559574E+06, -2.06077818756100E+06, -5.21445053212414E+07,
    // WT1
    +0, +0, +0, +0, +0, +0, +7.29841848989391E-04, -3.53899555749875E-02,
    +2.07797425718513E+00, -1.00464709786287E+02, +3.15206108877819E+03,
    -6.27054715090012E+04, +7.67135400969617E+05, -5.26074391316381E+06,
    +1.54721246264919E+07, +0,
    // WT2
    +0, +0, +0, +0, +0, +0, +2.36392855180768E-04, -9.16785337967013E-03,
    +4.62186525041313E-01, -1.96943786006540E+01, +4.99169195295559E+02,
    -6.21419845845090E+03, -2.81501182042707E+03, +1.13673298305631E+06,
    -1.34113464389309E+07, +5.21445053212414E+07,
    // WT3
    +0, +0, +0, +0, +0, +2.33766206773151E-07, -3.81542906607063E-05,
    +3.51416601267000E-03, -1.66538571864728E-01, +4.80006136831847E+00,
    -8.73165934223603E+01, +9.77683627474638E+02, -6.14479071209961E+03,
    +1.66000945117640E+04, +0, +0,
    // W0
    +0, +0, +0, +0, +0, -2.33766206773151E-07, -9.28080413509453E-04,
    +4.10436429419876E-02, -2.37362221036171E+00, +1.15359027018623E+02,
    -3.56391369065139E+03, +6.79419863399775E+04, -7.58175598497247E+05,
    +4.10741033864332E+06, -2.06077799132836E+06, -5.21445053212414E+07,
    //};
    // static double POLY4_35[] = {
    // RT0
    +0, +0, +0, +0, +0, +0, -4.45711399441838E-05, +1.27267770241379E-03,
    -2.36954961381262E-01, +1.54330657903756E+01, -5.22799159267808E+02,
    +1.05951216669313E+04, -1.29194382386499E+05, +8.72975373557709E+05,
    -2.51177235556236E+06, +0,
    // RT1
    +0, +0, +0, +0, +0, +0, +0, -7.85617372254488E-02, +6.35653573484868E+00,
    -3.38296938763990E+02, +1.25120495802096E+04, -3.16847570511637E+05,
    +5.38614211391604E+06, -5.87119005093822E+07, +3.70104713293016E+08,
    -1.02427466127427E+09,
    // RT2
    +0, +0, +0, +0, +0, +0, +0, -2.37900485051067E-01, +1.84122184400896E+01,
    -1.00200731304146E+03, +3.75151841595736E+04, -9.50626663390130E+05,
    +1.60419390230055E+07, -1.72465289687396E+08, +1.06625915044526E+09,
    -2.88139014651985E+09,
    // RT3
    +0, +0, +0, +0, +0, +0, -6.00691586407385E-04, -3.64479545338439E-01,
    +1.57496131755179E+01, -6.54944248734901E+02, +1.70830039597097E+04,
    -2.90517939780207E+05, +2.96817940164703E+06, -1.64944522586065E+07,
    +3.49059698304732E+07, +0,
    // WT0
    +0, +0, +0, +0, +0, +0, -9.71977163623582E-04, +4.46336825474679E-02,
    -2.54039585508437E+00, +1.20162876508281E+02, -3.65154015572653E+03,
    +6.89267810537827E+04, -7.64375918906505E+05, +4.12401093010750E+06,
    -2.06077818756100E+06, -5.21445053212414E+07,
    // WT1
    +0, +0, +0, +0, +0, +0, +7.29841848989391E-04, -3.53899555749875E-02,
    +2.07797425718513E+00, -1.00464709786287E+02, +3.15206108877819E+03,
    -6.27054715090012E+04, +7.67135400969617E+05, -5.26074391316381E+06,
    +1.54721246264919E+07, +0,
    // WT2
    +0, +0, +0, +0, +0, +0, +2.36392855180768E-04, -9.16785337967013E-03,
    +4.62186525041313E-01, -1.96943786006540E+01, +4.99169195295559E+02,
    -6.21419845845090E+03, -2.81501182042707E+03, +1.13673298305631E+06,
    -1.34113464389309E+07, +5.21445053212414E+07,
    // WT3
    +0, +0, +0, +0, +0, +0, +5.74245945342286E-06, -7.58735928102351E-05,
    +2.35072857922892E-04, -3.78812134013125E-03, +3.09871652785805E-01,
    -7.11108633061306E+00, +5.55297573149528E+01, +0, +0, +0,
    // W0
    +0, +0, +0, +0, +0, +0, -9.71977163623582E-04, +4.46336825474679E-02,
    -2.54039585508437E+00, +1.20162876508281E+02, -3.65154015572653E+03,
    +6.89267810537827E+04, -7.64375918966661E+05, +4.12401043315509E+06,
    -2.06077799132836E+06, -5.21445053212414E+07,
    //};
    // static double POLY4_53[] = {
    // RT0
    +0, +0, +0, +0, +0, +0, +0, +0, +0, -4.07557525914600E-05,
    -6.88846864931685E-04, +1.74725309199384E-02, +0, +0, +0, +0,
    // RT1
    +0, +0, +0, +0, +0, +0, +0, +0, +0, -3.62569791162153E-04,
    -9.09231717268466E-03, +1.84336760556262E-01, +0, +0, +0, +0,
    // RT2
    +0, +0, +0, +0, +0, +0, +0, +0, +0, -9.65842534508637E-04,
    -4.49822013469279E-02, +6.08784033347757E-01, +0, +0, +0, +0,
    // RT3
    +0, +0, +0, +0, +0, +0, +0, +0, +0, -2.19135070169653E-03,
    -1.19108256987623E-01, -7.50238795695573E-01, +0, +0, +0, +0,
    // WT0
    +0, +0, +0, +0, +0, +0, +0, +0, +0, -8.30435807003709E-04,
    +1.65249927447633E-02, -1.02764502206812E-01, +0, +0, +0, +0,
    // WT1
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +6.16374517326469E-04,
    -1.26711744680092E-02, +8.14504890732155E-02, +0, +0, +0, +0,
    // WT2
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +2.08294969857230E-04,
    -3.77489954837361E-03, +2.09857151617436E-02, +0, +0, +0, +0,
    // WT3
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +5.76631982000990E-06,
    -7.89187283804890E-05, +3.28297971853126E-04, +0, +0, +0, +0,
    // W0
    +0, +0, +0, +0, +0, +0, +0, +0, +0, -8.30435807003709E-04,
    +1.65249927447633E-02, -1.02764502206812E-01, +0, +0, +0, +0,
    //};
    // static double POLY4_RBASE[] = {
    1.45303521503316E-01, 1.33909728812636E+00, 3.92696350135829E+00,
    8.58863568901199E+00,
    //};
    // static double POLY4_WBASE[] = {
    7.46024515358156E-01, 2.34479815323517E-01, 1.92704402415764E-02,
    2.25229076750736E-04,
    //};

    // static double POLY5_1[] = {
    // RT0
    +0, +0, +0, +0, +0, +0, +0, +0, +0, -4.46679165328413E-11,
    +1.21879111988031E-09, -2.62975022612104E-08, +5.15106194905897E-07,
    -9.27933625824749E-06, +1.51794097682482E-04, -2.15865967920301E-03,
    +2.26659266316985E-02,
    // RT1
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +1.93117331714174E-10,
    -4.57267589660699E-09, +2.48339908218932E-08, +1.50716729438474E-06,
    -6.07268757707381E-05, +1.37506939145643E-03, -2.20258754419939E-02,
    +2.31271692140905E-01,
    // RT2
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +4.84989776180094E-09,
    +1.31538893944284E-07, -2.766753852879E-06, -7.651163510626E-05,
    +4.033058545972E-03, -8.16520022916145E-02, +8.57346024118779E-01,
    // RT3
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, -2.48581772214623E-07,
    -4.34482635782585E-06, -7.46018257987630E-07, +1.01210776517279E-02,
    -2.83193369640005E-01, +2.97353038120345E+00,
    // RT4
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, -8.92432153868554E-09,
    +1.77288899268988E-08, +3.040754680666E-06, +1.058229325071E-04,
    +4.596379534985E-02, -1.75382723579114E+00, +1.84151859759049E+01,
    // WT0
    +0, +0, +0, +0, +0, +0, +0, +0, +0, -2.03822632771791E-09,
    +3.89110229133810E-08, -5.84914787904823E-07, +8.30316168666696E-06,
    -1.13218402310546E-04, +1.49128888586790E-03, -1.96867576904816E-02,
    +2.95524224714749E-01,
    // WT1
    +0, +0, +0, +0, +0, +0, +0, +0, +8.62848118397570E-09,
    -1.38975551148989E-07, +1.602894068228E-06, -1.646364300836E-05,
    +1.538445806778E-04, -1.28848868034502E-03, +9.38866933338584E-03,
    -5.61737590178812E-02, +2.69266719309991E-01,
    // WT2
    +0, +0, +0, +0, +0, +0, +0, -9.41953204205665E-09, +1.47452251067755E-07,
    -1.57456991199322E-06, +1.45098401798393E-05, -1.18858834181513E-04,
    +8.53697675984210E-04, -5.22877807397165E-03, +2.60854524809786E-02,
    -9.71152726809059E-02, +2.19086362515979E-01,
    // WT3
    +0, +0, +0, +0, +0, +0, +0, -3.84961617022042E-08, +5.66595396544470E-07,
    -5.52351805403748E-06, +4.53160377546073E-05, -3.22542784865557E-04,
    +1.95682017370967E-03, -9.77232537679229E-03, +3.79455945268632E-02,
    -1.02979262192227E-01, +1.49451349150573E-01,
    // WT4
    +0, +0, +0, +0, +0, +0, +4.09594812521430E-09, -6.47097874264417E-08,
    +6.743541482689E-07, -5.917993920224E-06, +4.531969237381E-05,
    -2.99102856679638E-04, +1.65695765202643E-03, -7.40671222520653E-03,
    +2.50889946832192E-02, -5.73782817487958E-02, +6.66713443086877E-02,
    //};
    // static double POLY5_5[] = {
    // RT0
    +0, +0, +0, +0, +0, +0, +0, -2.58163897135138E-14, +8.14127461488273E-13,
    -2.11414838976129E-11, +5.09822003260014E-10, -1.16002134438663E-08,
    +2.46810694414540E-07, -4.92556826124502E-06, +9.02580687971053E-05,
    -1.45190025120726E-03, +1.73416786387475E-02,
    // RT1
    +0, +0, +0, +0, +0, +0, +1.04525287289788E-14, +5.44611782010773E-14,
    -4.831059411392E-12, +1.136643908832E-10, -1.104373076913E-09,
    -2.35346740649916E-08, +1.43772622028764E-06, -4.23405023015273E-05,
    +9.12034574793379E-04, -1.52479441718739E-02, +1.76055265928744E-01,
    // RT2
    +0, +0, +0, +0, +0, +0, -6.89693150857911E-14, +5.92064260918861E-13,
    +1.847170956043E-11, -3.390752744265E-10, -2.995532064116E-09,
    +1.57456141058535E-07, -3.95859409711346E-07, -9.58924580919747E-05,
    +3.23551502557785E-03, -5.97587007636479E-02, +6.46432853383057E-01,
    // RT3
    +0, +0, +0, +0, +0, +0, +0, -3.61293809667763E-12, -2.70803518291085E-11,
    +8.83758848468769E-10, +1.59166632851267E-08, -1.32581997983422E-07,
    -7.60223407443995E-06, -7.41019244900952E-05, +9.81432631743423E-03,
    -2.23055570487771E-01, +2.21460798080643E+00,
    // RT4
    +0, +0, +0, +0, +0, +0, +7.12332088345321E-13, +3.16578501501894E-12,
    -8.776668218053E-11, -2.342817613343E-09, -3.496962018025E-08,
    -3.03172870136802E-07, +1.50511293969805E-06, +1.37704919387696E-04,
    +4.70723869619745E-02, -1.47486623003693E+00, +1.35704792175847E+01,
    // WT0
    +0, +0, +0, +0, +0, +0, +1.04348658616398E-13, -1.94147461891055E-12,
    +3.485512360993E-11, -6.277497362235E-10, +1.100758247388E-08,
    -1.88329804969573E-07, +3.12338120839468E-06, -5.04404167403568E-05,
    +8.00338056610995E-04, -1.30892406559521E-02, +2.47383140241103E-01,
    // WT1
    +0, +0, +0, +0, +3.23496149760478E-14, -5.24314473469311E-13,
    +7.743219385056E-12, -1.146022750992E-10, +1.615238462197E-09,
    -2.15479017572233E-08, +2.70933462557631E-07, -3.18750295288531E-06,
    +3.47425221210099E-05, -3.45558237388223E-04, +3.05779768191621E-03,
    -2.29118251223003E-02, +1.59834227924213E-01,
    // WT2
    +0, +0, +0, -3.42790561802876E-14, +5.26475736681542E-13,
    -7.184330797139E-12, +9.763932908544E-11, -1.244014559219E-09,
    +1.472744068942E-08, -1.611749975234E-07, +1.616487851917E-06,
    -1.46852359124154E-05, +1.18900349101069E-04, -8.37562373221756E-04,
    +4.93752683045845E-03, -2.25514728915673E-02, +6.95211812453929E-02,
    // WT3
    +0, +0, +1.04072340345039E-14, -1.60808044529211E-13, +2.183534866798E-12,
    -2.939403008391E-11, +3.679254029085E-10, -4.23775673047899E-09,
    +4.46559231067006E-08, -4.26488836563267E-07, +3.64721335274973E-06,
    -2.74868382777722E-05, +1.78586118867488E-04, -9.68428981886534E-04,
    +4.16002324339929E-03, -1.28290192663141E-02, +2.22353727685016E-02,
    // WT4
    +0, -8.16770412525963E-16, +1.31376515047977E-14, -1.856950818865E-13,
    +2.596836515749E-12, -3.372639523006E-11, +4.025371849467E-10,
    -4.389453269417E-09, +4.332753856271E-08, -3.82673275931962E-07,
    +2.98006900751543E-06, -2.00718990300052E-05, +1.13876001386361E-04,
    -5.23627942443563E-04, +1.83524565118203E-03, -4.37785737450783E-03,
    +5.36963805223095E-03,
    //};
    // static double POLY5_10[] = {
    // RT0
    +0, +0, +0, +0, +0, +0, +0, -1.13825201010775E-14, +1.89737681670375E-13,
    -4.81561201185876E-12, +1.56666512163407E-10, -3.73782213255083E-09,
    +9.15858355075147E-08, -2.13775073585629E-06, +4.56547356365536E-05,
    -8.68003909323740E-04, +1.22703754069176E-02,
    // RT1
    +0, +0, +0, +0, +0, +0, -3.67160504428358E-15, +1.27876280158297E-14,
    -1.296476623788E-12, +1.477175434354E-11, +5.464102147892E-10,
    -2.42538340602723E-08, +8.20460740637617E-07, -2.20379304598661E-05,
    +4.90295372978785E-04, -9.14294111576119E-03, +1.22590403403690E-01,
    // RT2
    +0, +0, +0, +0, +0, +0, +1.39017367502123E-14, -6.96391385426890E-13,
    +1.176946020731E-12, +1.725627235645E-10, -3.686383856300E-09,
    +2.87495324207095E-08, +1.71307311000282E-06, -7.94273603184629E-05,
    +2.00938064965897E-03, -3.63329491677178E-02, +4.34393683888443E-01,
    // RT3
    +0, +0, +0, +0, +0, -1.27815158195209E-14, +1.99910415869821E-14,
    +3.753542914426E-12, -2.708018219579E-11, -1.190574776587E-09,
    +1.106696436509E-08, +3.954955671326E-07, -4.398596059588E-06,
    -2.01087998907735E-04, +7.89092425542937E-03, -1.42056749162695E-01,
    +1.39964149420683E+00,
    // RT4
    +0, +0, +0, +0, +0, -1.19442341030461E-13, -2.34074833275956E-12,
    +6.861649627426E-12, +6.082671496226E-10, +5.381160105420E-09,
    -6.253297138700E-08, -2.135966835050E-06, -2.373394341886E-05,
    +2.88711171412814E-06, +4.85221195290753E-02, -1.04346091985269E+00,
    +7.89901551676692E+00,
    // WT0
    +0, +0, +0, +0, +0, +0, +7.95526040108997E-15, -2.48593096128045E-13,
    +4.761246208720E-12, -9.535763686605E-11, +2.225273630974E-09,
    -4.49796778054865E-08, +9.17812870287386E-07, -1.86764236490502E-05,
    +3.76807779068053E-04, -8.10456360143408E-03, +2.01097936411496E-01,
    // WT1
    +0, +0, +0, +0, +1.25678686624734E-15, -2.34266248891173E-14,
    +3.973252415832E-13, -6.830539401049E-12, +1.140771033372E-10,
    -1.82546185762009E-09, +2.77209637550134E-08, -4.01726946190383E-07,
    +5.48227244014763E-06, -6.95676245982121E-05, +8.05193921815776E-04,
    -8.15528438784469E-03, +9.71769901268114E-02,
    // WT2
    +0, +0, +0, -8.20929494859896E-16, +1.37356038393016E-14,
    -2.022863065220E-13, +3.058055403795E-12, -4.387890955243E-11,
    +5.923946274445E-10, -7.503659964159E-09, +8.851599803902E-08,
    -9.65561998415038E-07, +9.60884622778092E-06, -8.56551787594404E-05,
    +6.66057194311179E-04, -4.17753183902198E-03, +2.25443826852447E-02,
    // WT3
    +0, -1.08764612488790E-17, +1.85299909689937E-16, -2.730195628655E-15,
    +4.127368817265E-14, -5.881379088074E-13, +7.805245193391E-12,
    -9.632707991704E-11, +1.099047050624E-09, -1.15042731790748E-08,
    +1.09415155268932E-07, -9.33687124875935E-07, +7.02338477986218E-06,
    -4.53759748787756E-05, +2.41722511389146E-04, -9.75935943447037E-04,
    +2.57520532789644E-03,
    // WT4
    +7.28996979748849E-19, -1.26518146195173E-17, +1.886145834486E-16,
    -2.876728287383E-15, +4.114588668138E-14, -5.44436631413933E-13,
    +6.64976446790959E-12, -7.44560069974940E-11, +7.57553198166848E-10,
    -6.92956101109829E-09, +5.62222859033624E-08, -3.97500114084351E-07,
    +2.39039126138140E-06, -1.18023950002105E-05, +4.52254031046244E-05,
    -1.21113782150370E-04, +1.75013126731224E-04,
    //};
    // static double POLY5_15[] = {
    // RT0
    +0, +0, +0, +0, +0, -4.16387977337393E-17, +7.20872997373860E-16,
    +1.395993802064E-14, +3.660484641252E-14, -4.154857548139E-12,
    +2.301379846544E-11, -1.033307012866E-09, +3.997777641049E-08,
    -9.35118186333939E-07, +2.38589932752937E-05, -5.35185183652937E-04,
    +8.85218988709735E-03,
    // RT1
    +0, +0, +0, +0, +0, -4.56279214732217E-16, +6.24941647247927E-15,
    +1.737896339191E-13, +8.964205979517E-14, -3.538906780633E-11,
    +9.561341254948E-11, -9.772831891310E-09, +4.240340194620E-07,
    -1.02384302866534E-05, +2.57987709704822E-04, -5.54735977651677E-03,
    +8.68245143991948E-02,
    // RT2
    +0, +0, +0, +0, +0, -2.52879337929239E-15, +2.13925810087833E-14,
    +7.884307667104E-13, -9.023398159510E-13, -5.814101544957E-11,
    -1.333480437968E-09, -2.217064940373E-08, +1.643290788086E-06,
    -4.39602147345028E-05, +1.08648982748911E-03, -2.13014521653498E-02,
    +2.94150684465425E-01,
    // RT3
    +0, +0, +0, +0, +0, -6.42391438038888E-15, +5.37848223438815E-15,
    +8.960828117859E-13, +5.214153461337E-11, -1.106601744067E-10,
    -2.007890743962E-08, +1.543764346501E-07, +4.520749076914E-06,
    -1.88893338587047E-04, +4.73264487389288E-03, -7.91197893350253E-02,
    +8.60057928514554E-01,
    // RT4
    +0, +0, +0, +0, -2.24366166957225E-14, +4.87224967526081E-14,
    +5.587369053655E-12, -3.045253104617E-12, -1.223983883080E-09,
    -2.05603889396319E-09, +2.58604071603561E-07, +1.34240904266268E-06,
    -5.72877569731162E-05, -9.56275105032191E-04, +4.23367010370921E-02,
    -5.76800927133412E-01, +3.87328263873381E+00,
    // WT0
    +0, +0, +0, +0, +0, +0, +8.98007931950169E-15, +7.25673623859497E-14,
    +5.851494250405E-14, -4.234204823846E-11, +3.911507312679E-10,
    -9.65094802088511E-09, +3.42197444235714E-07, -7.51821178144509E-06,
    +1.94218051498662E-04, -5.38533819142287E-03, +1.68122596736809E-01,
    // WT1
    +0, +0, +0, +0, +0, -1.05490525395105E-15, +1.96855386549388E-14,
    -5.500330153548E-13, +1.003849567976E-11, -1.720997242621E-10,
    +3.533277061402E-09, -6.389171736029E-08, +1.046236652393E-06,
    -1.73148206795827E-05, +2.57820531617185E-04, -3.46188265338350E-03,
    +7.03302497508176E-02,
    // WT2
    +0, +0, +0, +0, +3.60020423754545E-16, -6.24245825017148E-15,
    +9.945311467434E-14, -1.749051512721E-12, +2.768503957853E-11,
    -4.08688551136506E-10, +6.04189063303610E-09, -8.23540111024147E-08,
    +1.01503783870262E-06, -1.20490761741576E-05, +1.26928442448148E-04,
    -1.05539461930597E-03, +1.15543698537013E-02,
    // WT3
    +0, +0, +2.51163533058925E-18, -4.31723745510697E-17, +6.557620865832E-16,
    -1.016528519495E-14, +1.491302084832E-13, -2.06638666222265E-12,
    +2.67958697789258E-11, -3.23322654638336E-10, +3.63722952167779E-09,
    -3.75484943783021E-08, +3.49164261987184E-07, -2.92658670674908E-06,
    +2.12937256719543E-05, -1.19434130620929E-04, +6.45524336158384E-04,
    // WT4
    +0, -1.29043630202811E-19, +2.16234952241296E-18, -3.107631557965E-17,
    +4.570804313173E-16, -6.301348858104E-15, +8.031304476153E-14,
    -9.446196472547E-13, +1.018245804339E-11, -9.96995451348129E-11,
    +8.77489010276305E-10, -6.84655877575364E-09, +4.64460857084983E-08,
    -2.66924538268397E-07, +1.24621276265907E-06, -4.30868944351523E-06,
    +9.94307982432868E-06,
    //};
    // static double POLY5_20[] = {
    // RT0
    +0, +0, +0, +0, +0, +1.91875764545740E-16, +7.8357401095707E-16,
    -3.260875931644E-14, -1.186752035569E-13, +4.275180095653E-12,
    +3.357056136731E-11, -1.123776903884E-09, +1.231203269887E-08,
    -3.99851421361031E-07, +1.45418822817771E-05, -3.49912254976317E-04,
    +6.67768703938812E-03,
    // RT1
    +0, +0, +0, +0, +0, +2.02778478673555E-15, +1.01640716785099E-14,
    -3.385363492036E-13, -1.615655871159E-12, +4.527419140333E-11,
    +3.853670706486E-10, -1.184607130107E-08, +1.347873288827E-07,
    -4.47788241748377E-06, +1.54942754358273E-04, -3.55524254280266E-03,
    +6.44912219301603E-02,
    // RT2
    +0, +0, +0, +0, +0, +7.79850771456444E-15, +6.00464406395001E-14,
    -1.249779730869E-12, -1.020720636353E-11, +1.814709816693E-10,
    +1.766397336977E-09, -4.603559449010E-08, +5.863956443581E-07,
    -2.03797212506691E-05, +6.31405161185185E-04, -1.30102750145071E-02,
    +2.10244289044705E-01,
    // RT3
    +0, +0, +0, +0, -2.92397030777912E-15, +1.94152129078465E-14,
    +4.859447665850E-13, -3.217227223463E-12, -7.484522135512E-11,
    +7.19101516047753E-10, +6.88409355245582E-09, -1.44374545515769E-07,
    +2.74941013315834E-06, -1.02790452049013E-04, +2.59924221372643E-03,
    -4.35712368303551E-02, +5.62170709585029E-01,
    // RT4
    +0, +0, +0, +0, +1.17976126840060E-14, +1.24156229350669E-13,
    -3.892741622280E-12, -7.755793199043E-12, +9.492190032313E-10,
    -4.98680128123353E-09, -1.81502268782664E-07, +2.69463269394888E-06,
    +2.50032154421640E-05, -1.33684303917681E-03, +2.29121951862538E-02,
    -2.45653725061323E-01, +1.89999883453047E+00,
    // WT0
    +0, +0, +0, +0, +0, +1.74841995087592E-15, -6.95671892641256E-16,
    -3.000659497257E-13, +2.021279817961E-13, +3.853596935400E-11,
    +1.461418533652E-10, -1.014517563435E-08, +1.132736008979E-07,
    -2.86605475073259E-06, +1.21958354908768E-04, -3.86293751153466E-03,
    +1.45298342081522E-01,
    // WT1
    +0, +0, +0, +0, +0, -1.11199320525573E-15, +1.85007587796671E-15,
    +1.220613939709E-13, +1.275068098526E-12, -5.341838883262E-11,
    +6.161037256669E-10, -1.009147879750E-08, +2.907862965346E-07,
    -6.12300038720919E-06, +1.00104454489518E-04, -1.80677298502757E-03,
    +5.78009914536630E-02,
    // WT2
    +0, +0, +0, +0, +0, -9.49816486853687E-16, +6.67922080354234E-15,
    +2.606163540537E-15, +1.983799950150E-12, -5.400548574357E-11,
    +6.638043374114E-10, -8.799518866802E-09, +1.791418482685E-07,
    -2.96075397351101E-06, +3.38028206156144E-05, -3.58426847857878E-04,
    +8.39213709428516E-03,
    // WT3
    +0, +0, +0, +0, +1.33829971060180E-17, -3.44841877844140E-16,
    +4.745009557656E-15, -6.033814209875E-14, +1.049256040808E-12,
    -1.70859789556117E-11, +2.15219425727959E-10, -2.52746574206884E-09,
    +3.27761714422960E-08, -3.90387662925193E-07, +3.46340204593870E-06,
    -2.43236345136782E-05, +3.54846978585226E-04,
    // WT4
    +0, +0, +2.69412277020887E-20, -4.24837886165685E-19, +6.030500065438E-18,
    -9.069722758289E-17, +1.246599177672E-15, -1.56872999797549E-14,
    +1.87305099552692E-13, -2.09498886675861E-12, +2.11630022068394E-11,
    -1.92566242323525E-10, +1.62012436344069E-09, -1.23621614171556E-08,
    +7.72165684563049E-08, -3.59858901591047E-07, +2.43682618601000E-06,
    //};
    // static double POLY5_25[] = {
    // RT0
    +0, +0, +0, +0, +0, +0, -1.13927848238726E-15, +7.39404133595713E-15,
    +1.445982921243E-13, -2.676703245252E-12, +5.823521627177E-12,
    +2.17264723874381E-10, +3.56242145897468E-09, -3.03763737404491E-07,
    +9.46859114120901E-06, -2.30896753853196E-04, +5.24663913001114E-03,
    // RT1
    +0, +0, +0, +0, +0, +2.89872355524581E-16, -1.22296292045864E-14,
    +6.184065097200E-14, +1.649846591230E-12, -2.729713905266E-11,
    +3.709913790650E-11, +2.216486288382E-09, +4.616160236414E-08,
    -3.32380270861364E-06, +9.84635072633776E-05, -2.30092118015697E-03,
    +5.00845183695073E-02,
    // RT2
    +0, +0, +0, +0, +0, +1.97068646590923E-15, -4.89419270626800E-14,
    +1.136466605916E-13, +7.546203883874E-12, -9.635646767455E-11,
    -8.295965491209E-11, +7.534109114453E-09, +2.699970652707E-07,
    -1.42982334217081E-05, +3.78290946669264E-04, -8.03133015084373E-03,
    +1.58689469640791E-01,
    // RT3
    +0, +0, +0, +0, +0, +1.33642069941389E-14, -1.55850612605745E-13,
    -7.522712577474E-13, +3.209520801187E-11, -2.075594313618E-10,
    -2.070575894402E-09, +7.323046997451E-09, +1.851491550417E-06,
    -6.37524802411383E-05, +1.36795464918785E-03, -2.42051126993146E-02,
    +3.97847167557815E-01,
    // RT4
    +0, +0, +0, +0, +0, -6.07053986130526E-14, +1.04447493138843E-12,
    -4.286617818951E-13, -2.632066100073E-10, +4.804518986559E-09,
    -1.835675889421E-08, -1.068175391334E-06, +3.292234974141E-05,
    -5.94805357558251E-04, +8.29382168612791E-03, -9.93122509049447E-02,
    +1.09857804755042E+00,
    // WT0
    +0, +0, +0, +0, +0, +0, -9.10338640266542E-15, +1.00438927627833E-13,
    +7.817349237071E-13, -2.547619474232E-11, +1.479321506529E-10,
    +1.52314028857627E-09, +9.20072040917242E-09, -2.19427111221848E-06,
    +8.65797782880311E-05, -2.82718629312875E-03, +1.28718310443295E-01,
    // WT1
    +0, +0, +0, +0, +0, +0, +5.52380927618760E-15, -6.43424400204124E-14,
    -2.358734508092E-13, +8.261326648131E-12, +9.229645304956E-11,
    -5.68108973828949E-09, +1.22477891136278E-07, -2.11919643127927E-06,
    +4.23605032368922E-05, -1.14423444576221E-03, +5.06607252890186E-02,
    // WT2
    +0, +0, +0, +0, +0, +0, +3.99457454087556E-15, -5.11826702824182E-14,
    -4.157593182747E-14, +4.214670817758E-12, +6.705582751532E-11,
    -3.36086411698418E-09, +6.07453633298986E-08, -7.40736211041247E-07,
    +8.84176371665149E-06, -1.72559275066834E-04, +7.16639814253567E-03,
    // WT3
    +0, +0, +0, +0, -2.14649508112234E-18, -2.45525846412281E-18,
    +6.126212599772E-16, -8.526651626939E-15, +4.826636065733E-14,
    -3.39554163649740E-13, +1.67070784862985E-11, -4.42671979311163E-10,
    +6.77368055908400E-09, -7.03520999708859E-08, +6.04993294708874E-07,
    -7.80555094280483E-06, +2.85954806605017E-04,
    // WT4
    +0, +0, +0, -5.63938733073804E-21, +6.92182516324628E-20,
    -1.586937691507E-18, +3.357639744582E-17, -4.810285046442E-16,
    +5.386312669975E-15, -6.117895297439E-14, +8.441808227634E-13,
    -1.18527596836592E-11, +1.36296870441445E-10, -1.17842611094141E-09,
    +7.80430641995926E-09, -5.97767417400540E-08, +1.65186146094969E-06,
    //};
    // static double POLY5_40[] = {
    // RT0
    +0, +0, +0, +0, +0, +0, +0, +0, -1.73363958895356E-06,
    +1.19921331441483E-04, -1.59437614121125E-02, +1.13467897349442E+00,
    -4.47216460864586E+01, +1.06251216612604E+03, -1.52073917378512E+04,
    +1.20662887111273E+05, -4.07186366852475E+05,
    // RT1
    +0, +0, +0, +0, +0, +0, +0, +0, -1.60102542621710E-05,
    +1.10331262112395E-03, -1.50043662589017E-01, +1.05563640866077E+01,
    -4.10468817024806E+02, +9.62604416506819E+03, -1.35888069838270E+05,
    +1.06107577038340E+06, -3.51190792816119E+06,
    // RT2
    +0, +0, +0, +0, +0, +0, +0, +0, -4.48880032128422E-05,
    +2.69025112122177E-03, -4.01048115525954E-01, +2.78360021977405E+01,
    -1.04891729356965E+03, +2.36985942687423E+04, -3.19504627257548E+05,
    +2.34879693563358E+06, -7.16341568174085E+06,
    // RT3
    +0, +0, +0, +0, +0, +0, +0, +0, -6.38526371092582E-05,
    -2.29263585792626E-03, -7.65735935499627E-02, +9.12692349152792E+00,
    -2.32077034386717E+02, +2.81839578728845E+02, +9.59529683876419E+04,
    -1.77638956809518E+06, +1.02489759645410E+07,
    // RT4
    +0, +0, +0, +0, +0, +0, +0, +0, -3.59049364231569E-05,
    -2.25963977930044E-02, +1.12594870794668E+00, -4.56752462103909E+01,
    +1.05804526830637E+03, -1.16003199605875E+04, -4.07297627297272E+04,
    +2.22215528319857E+06, -1.61196455032613E+07,
    // WT0
    +0, +0, +0, +0, +0, +0, +0, +2.45410444871290E-08, -5.44045676414454E-05,
    +4.69761739388539E-03, -3.44524636310293E-01, +1.86783516260836E+01,
    -6.65977874814000E+02, +1.52475971245819E+04, -2.16412375650404E+05,
    +1.73258425282146E+06, -5.97706577273881E+06,
    // WT1
    +0, +0, +0, +0, +0, +0, +0, +0, +2.77778345870650E-05,
    -2.22835017655890E-03, +1.61077633475573E-01, -8.96743743396132E+00,
    +3.28062687293374E+02, -7.65722701219557E+03, +1.10255055017664E+05,
    -8.92528122219324E+05, +3.10638627744347E+06,
    // WT2
    +0, +0, +0, +0, +0, +0, +0, +0, +1.83574464457207E-05,
    -1.54837969489927E-03, +1.18520453711586E-01, -6.69649981309161E+00,
    +2.44789386487321E+02, -5.68832664556359E+03, +8.14507604229357E+04,
    -6.55181056671474E+05, +2.26410896607237E+06,
    // WT3
    +0, +0, +0, +0, +0, +0, +0, -2.40799435809950E-08, +8.12621667601546E-06,
    -9.04491430884113E-04, +6.37686375770059E-02, -2.96135703135647E+00,
    +9.15142356996330E+01, -1.86971865249111E+03, +2.42945528916947E+04,
    -1.81852473229081E+05, +5.96854758661427E+05,
    // WT4
    +0, +0, +0, +0, +0, +0, +0, -4.61100906133970E-10, +1.43069932644286E-07,
    -1.63960915431080E-05, +1.15791154612838E-03, -5.30573476742071E-02,
    +1.61156533367153E+00, -3.23248143316007E+01, +4.12007318109157E+02,
    -3.02260070158372E+03, +9.71575094154768E+03,
    //};
    // static double POLY5_59[] = {
    // RT0
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, -2.43758528330205E-02,
    +2.07301567989771E+00, -6.45964225381113E+01, +7.14160088655470E+02, +0, +0,
    +0,
    // RT1
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, -2.28861955413636E-01,
    +1.93190784733691E+01, -5.99774730340912E+02, +6.61844165304871E+03, +0, +0,
    +0,
    // RT2
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, -6.95053039285586E-01,
    +5.76874090316016E+01, -1.77704143225520E+03, +1.95366082947811E+04, +0, +0,
    +0,
    // RT3
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, -1.58072809087018E+00,
    +1.27050801091948E+02, -3.86687350914280E+03, +4.23024828121420E+04, +0, +0,
    +0,
    // RT4
    +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, -3.33963830405396E+00,
    +2.51830424600204E+02, -7.57728527654961E+03, +8.21966816595690E+04, +0, +0,
    +0,
    // WT0
    +0, +0, +0, +0, +0, +0, +0, +0, -3.56569330040085E-05,
    +1.14288667818648E-03, -1.08701946511941E-02, +0, +0, +0, +0, +0, +0,
    // WT1
    +0, +0, +0, +0, +0, +0, +0, +0, +2.09539509123135E-05,
    -6.87646614786982E-04, +6.68743788585688E-03, +0, +0, +0, +0, +0, +0,
    // WT2
    +0, +0, +0, +0, +0, +0, +0, +0, +1.34547929260279E-05,
    -4.19389884772726E-04, +3.87706687610809E-03, +0, +0, +0, +0, +0, +0,
    // WT3
    +0, +0, +0, +0, +0, +0, +0, +0, +1.23464092261605E-06,
    -3.55224564275590E-05, +3.03274662192286E-04, +0, +0, +0, +0, +0, +0,
    // WT4
    +0, +0, +0, +0, +0, +0, +0, +0, +1.35482430510942E-08,
    -3.27722199212781E-07, +2.41522703684296E-06, +0, +0, +0, +0, +0, +0,
    //};
    // static double POLY5_RBASE[] = {
    1.17581320211778E-01, 1.07456201243690E+00, 3.08593744371754E+00,
    6.41472973366203E+00, 1.18071894899717E+01,
    //};
    // static double POLY5_WBASE[] = {
    6.89284669864039E-01, 2.70967405960535E-01, 3.82231610015404E-02,
    1.51614186862443E-03, 8.62130526143657E-06,
    //};
};

__device__ inline void _CINT_clenshaw_d1(
    double *rr, const double *x, double u, int nroots) {
    /*
    reference
    https://github.com/sunqm/qcint/blob/38fa7cd87e5251e0bbb5abc549dbacc45f9da56e/src/polyfits.c
    */
    int i;
    double d0, d1, g0, g1;
    double u2 = u * 2.;

    for (i = 0; i < nroots - 1; i += 2) {
        d0 = 0;
        d1 = 0;
        g0 = x[13 + 14 * i];
        g1 = x[13 + 14 + 14 * i];
        d0 = u2 * g0 - d0 + x[12 + 14 * i];
        d1 = u2 * g1 - d1 + x[12 + 14 + 14 * i];
        g0 = u2 * d0 - g0 + x[11 + 14 * i];
        g1 = u2 * d1 - g1 + x[11 + 14 + 14 * i];
        d0 = u2 * g0 - d0 + x[10 + 14 * i];
        d1 = u2 * g1 - d1 + x[10 + 14 + 14 * i];
        g0 = u2 * d0 - g0 + x[9 + 14 * i];
        g1 = u2 * d1 - g1 + x[9 + 14 + 14 * i];
        d0 = u2 * g0 - d0 + x[8 + 14 * i];
        d1 = u2 * g1 - d1 + x[8 + 14 + 14 * i];
        g0 = u2 * d0 - g0 + x[7 + 14 * i];
        g1 = u2 * d1 - g1 + x[7 + 14 + 14 * i];
        d0 = u2 * g0 - d0 + x[6 + 14 * i];
        d1 = u2 * g1 - d1 + x[6 + 14 + 14 * i];
        g0 = u2 * d0 - g0 + x[5 + 14 * i];
        g1 = u2 * d1 - g1 + x[5 + 14 + 14 * i];
        d0 = u2 * g0 - d0 + x[4 + 14 * i];
        d1 = u2 * g1 - d1 + x[4 + 14 + 14 * i];
        g0 = u2 * d0 - g0 + x[3 + 14 * i];
        g1 = u2 * d1 - g1 + x[3 + 14 + 14 * i];
        d0 = u2 * g0 - d0 + x[2 + 14 * i];
        d1 = u2 * g1 - d1 + x[2 + 14 + 14 * i];
        g0 = u2 * d0 - g0 + x[1 + 14 * i];
        g1 = u2 * d1 - g1 + x[1 + 14 + 14 * i];
        rr[i] = u * g0 - d0 + x[14 * i] * 0.5;
        rr[(i + 1)] = u * g1 - d1 + x[14 * i + 14] * 0.5;
    }

    if (i < nroots) {
        d0 = 0;
        g0 = x[13 + 14 * i];
        d0 = u2 * g0 - d0 + x[12 + 14 * i];
        g0 = u2 * d0 - g0 + x[11 + 14 * i];
        d0 = u2 * g0 - d0 + x[10 + 14 * i];
        g0 = u2 * d0 - g0 + x[9 + 14 * i];
        d0 = u2 * g0 - d0 + x[8 + 14 * i];
        g0 = u2 * d0 - g0 + x[7 + 14 * i];
        d0 = u2 * g0 - d0 + x[6 + 14 * i];
        g0 = u2 * d0 - g0 + x[5 + 14 * i];
        d0 = u2 * g0 - d0 + x[4 + 14 * i];
        g0 = u2 * d0 - g0 + x[3 + 14 * i];
        d0 = u2 * g0 - d0 + x[2 + 14 * i];
        g0 = u2 * d0 - g0 + x[1 + 14 * i];
        rr[i] = u * g0 - d0 + x[14 * i] * 0.5;
    }
}
__device__ inline void polyfit_roots(
    int nroots, double x, double *rr, double *ww) {
    // for nroots >= 6 only!
    if (x < 3.e-10) {
        int off = nroots * (nroots - 1) / 2 - 15;
        for (int i = 0; i < nroots; i++) {
            rr[i] = POLY_SMALLX_R0[off + i] + POLY_SMALLX_R1[off + i] * x;
            ww[i] = POLY_SMALLX_W0[off + i] + POLY_SMALLX_W1[off + i] * x;
        }
        return;
    } else if (x > 35 + nroots * 5) {
        int off = nroots * (nroots - 1) / 2 - 15;
        double rt;
        double t = sqrt(PIE4 / x);
        for (int i = 0; i < nroots; i++) {
            rt = POLY_LARGEX_RT[off + i];
            rr[i] = rt / (x - rt);
            ww[i] = POLY_LARGEX_WW[off + i] * t;
        }
        return;
    }
    const double *datax = DATA_X + ((nroots - 1) * nroots / 2 - 15) * 14 * 31;
    const double *dataw = DATA_W + ((nroots - 1) * nroots / 2 - 15) * 14 * 31;
    int it;
    double tt;
    if (x <= 40) {
        it = (int)(x * .4);
        tt = (x - it * 2.5) * 0.8 - 1.;
    } else {
        x -= 40.;
        it = (int)(x * .25);
        tt = (x - it * 4.) * 0.5 - 1.;
        it += 16;
    }
    int offset = nroots * 14 * it;
    _CINT_clenshaw_d1(rr, datax + offset, tt, nroots);
    _CINT_clenshaw_d1(ww, dataw + offset, tt, nroots);
}

template <int NROOTS>
__device__ inline void GINTrys_root(double x, double *rw) {
    polyfit_roots(NROOTS, x, &rw[0], &rw[NROOTS]);
}
template <> __device__ inline void GINTrys_root<1>(double x, double *rw) {
    if (x < 3.e-10) {
        rw[0] = 0.5;
        rw[1] = 1.;
    } else {
        double tt = sqrt(x);
        double fmt0 = SQRTPIE4 / tt * erf(tt);
        rw[1] = fmt0;
        double e = exp(-x);
        double b = .5 / x;
        double fmt1 = b * (fmt0 - e);
        rw[0] = fmt1 / (fmt0 - fmt1);
    }
}

template <> __device__ inline void GINTrys_root<2>(double x, double *rw) {
    double rt0, rt1, wt0, wt1, y, z, cw, cr, ex, x1, x2, sx, f1;
    const double *p;

    if (x < 3e-10) {
        rt0 = 1.30693606237085E-01 - 2.90430236082028E-02 * x;
        rt1 = 2.86930639376291E+00 - 6.37623643058102E-01 * x;
        wt0 = 6.52145154862545E-01 - 1.22713621927067E-01 * x;
        wt1 = 3.47854845137453E-01 - 2.10619711404725E-01 * x;
    } else {
        ex = exp(-x);
        x1 = 1 / x;
        sx = sqrt(PIE4 * x1);
        if (x < 33.) {
            y = x;
            z = x;
            rt0 = 0;
            rt1 = 0;
            wt0 = 0;
            cr = 1.;
            if (x < 1.) {
                wt0 = ex;
                cw = x * 2;
                p = FITTING_DATA + POLY2_1;
            } else if (x < 3.) {
                y = x - 2.0;
                z = y;
                wt0 = ex;
                cw = x * 2;
                p = FITTING_DATA + POLY2_3;
            } else if (x < 5.) {
                y = x - 4.0;
                z = y;
                wt0 = ex;
                cw = x * 2;
                p = FITTING_DATA + POLY2_5;
            } else if (x < 10.) {
                y = x - 7.5;
                z = x1;
                cw = ex;
                wt0 = sx;
                p = FITTING_DATA + POLY2_10;

            } else {
                x2 = x1 * x1;
                cw = ex * x2;
                if (x < 15.) {
                    cw *= x2;
                    p = FITTING_DATA + POLY2_15;
                } else {
                    p = FITTING_DATA + POLY2_33;
                }
                cr = cw;
                wt0 = sx;
                rt0 = FITTING_DATA[POLY2_RBASE + 0] /
                      (x - FITTING_DATA[POLY2_RBASE + 0]);
                rt1 = FITTING_DATA[POLY2_RBASE + 1] /
                      (x - FITTING_DATA[POLY2_RBASE + 1]);
            }

            rt0 += FP15(y) * cr;
            p += 15;
            rt1 += FP15(y) * cr;
            p += 15;
            wt0 += FP15(z) * cw;
            f1 = (wt0 - ex) * x1 * .5;
            wt1 = ((f1 - wt0) * rt0 + f1) * (1. + rt1) / (rt1 - rt0);
            wt0 -= wt1;

        } else {
            rt0 = FITTING_DATA[POLY2_RBASE + 0] /
                  (x - FITTING_DATA[POLY2_RBASE + 0]);
            rt1 = FITTING_DATA[POLY2_RBASE + 1] /
                  (x - FITTING_DATA[POLY2_RBASE + 1]);
            wt0 = FITTING_DATA[POLY2_WBASE + 0] * sx;
            wt1 = FITTING_DATA[POLY2_WBASE + 1] * sx;
            p = FITTING_DATA + POLY2_40;
            if (x < 40.) {
                rt0 += (p[0] * x + p[1]) * ex;
                rt1 += (p[2] * x + p[3]) * ex;
                wt0 += (p[4] * x + p[5]) * ex;
                wt1 += (p[6] * x + p[7]) * ex;
            }
        }
    }
    rw[0] = rt0;
    rw[1] = rt1;
    rw[2] = wt0;
    rw[3] = wt1;
}

template <> __device__ inline void GINTrys_root<3>(double x, double *rw) {
    double rt0, rt1, rt2, wt0, wt1, wt2, t1, t2, t3, a1, a2, f1, f2;
    double y, z, cw, cr, ex, x1, sx;
    const double *p;

    if (x < 3.e-10) {
        rt0 = 6.03769246832797E-02 - 9.28875764357368E-03 * x;
        rt1 = 7.76823355931043E-01 - 1.19511285527878E-01 * x;
        rt2 = 6.66279971938567E+00 - 1.02504611068957E+00 * x;
        wt0 = 4.67913934572691E-01 - 5.64876917232519E-02 * x;
        wt1 = 3.60761573048137E-01 - 1.49077186455208E-01 * x;
        wt2 = 1.71324492379169E-01 - 1.27768455150979E-01 * x;
    } else {
        ex = exp(-x);
        x1 = 1. / x;
        sx = sqrt(PIE4 * x1);
        if (x < 33.) {
            y = x;
            z = x;
            rt0 = 0;
            rt1 = 0;
            rt2 = 0;
            wt0 = 0;
            cr = 1.;
            if (x < 5.) {
                if (x < 1.) {
                    p = FITTING_DATA + POLY3_1;
                } else if (x < 3.) {
                    y = x - 2.0;
                    z = y;
                    p = FITTING_DATA + POLY3_3;
                } else { // x < 5
                    y = x - 4.0;
                    z = y;
                    p = FITTING_DATA + POLY3_5;
                }
            } else {
                cw = ex;
                wt0 = sx;
                if (x < 10.) {
                    y = x - 7.5;
                    z = x1;
                    p = FITTING_DATA + POLY3_10;
                } else if (x < 15) {
                    y = x - 12.5;
                    z = x1;
                    p = FITTING_DATA + POLY3_15;
                } else {
                    cr = ex * x1 * x1;
                    if (x < 20) {
                        cr *= x1;
                        p = FITTING_DATA + POLY3_20;
                    } else { // x < 33
                        p = FITTING_DATA + POLY3_33;
                    }
                    cw = cr;
                    rt0 = FITTING_DATA[POLY3_RBASE + 0] /
                          (x - FITTING_DATA[POLY3_RBASE + 0]);
                    rt1 = FITTING_DATA[POLY3_RBASE + 1] /
                          (x - FITTING_DATA[POLY3_RBASE + 1]);
                    rt2 = FITTING_DATA[POLY3_RBASE + 2] /
                          (x - FITTING_DATA[POLY3_RBASE + 2]);
                }
            }

            rt0 += FP14(y) * cr;
            p += 14;
            rt1 += FP14(y) * cr;
            p += 14;
            rt2 += FP14(y) * cr;
            p += 14;
            f2 = FP14(z);

            if (x < 5.) {
                f1 = ((x + x) * f2 + ex) / 3.;
                wt0 = (x + x) * f1 + ex;
            } else {
                wt0 += f2 * cw;
                f1 = (wt0 - ex) * x1 * .5;
                f2 = (f1 * 3 - ex) * x1 * .5;
            }

            t1 = rt0 / (rt0 + 1.);
            t2 = rt1 / (rt1 + 1.);
            t3 = rt2 / (rt2 + 1.);
            a1 = f1 - t1 * wt0;
            a2 = f2 - t1 * f1;
            wt1 = (t3 * a1 - a2) / ((t3 - t2) * (t2 - t1));
            wt2 = (a2 - t2 * a1) / ((t3 - t2) * (t3 - t1));
            wt0 -= wt1 + wt2;
        } else { // x >= 33
            rt0 = FITTING_DATA[POLY3_RBASE + 0] /
                  (x - FITTING_DATA[POLY3_RBASE + 0]);
            rt1 = FITTING_DATA[POLY3_RBASE + 1] /
                  (x - FITTING_DATA[POLY3_RBASE + 1]);
            rt2 = FITTING_DATA[POLY3_RBASE + 2] /
                  (x - FITTING_DATA[POLY3_RBASE + 2]);
            wt0 = FITTING_DATA[POLY3_WBASE + 0] * sx;
            wt1 = FITTING_DATA[POLY3_WBASE + 1] * sx;
            wt2 = FITTING_DATA[POLY3_WBASE + 2] * sx;
            if (x < 47.) {
                p = FITTING_DATA + POLY3_47;
                rt0 += FP4(x) * ex;
                p += 4;
                rt1 += FP4(x) * ex;
                p += 4;
                rt2 += FP4(x) * ex;
                p += 4;
                wt0 += FP4(x) * ex;
                p += 4;
                wt1 += FP4(x) * ex;
                p += 4;
                wt2 += FP4(x) * ex;
            }
        }
    }
    rw[0] = rt0;
    rw[1] = rt1;
    rw[2] = rt2;
    rw[3] = wt0;
    rw[4] = wt1;
    rw[5] = wt2;
}

template <> __device__ inline void GINTrys_root<4>(double x, double *rw) {
    double rt0, rt1, rt2, rt3, wt0, wt1, wt2, wt3;
    double y, z, cr, cw, ex, x1, sx;
    const double *p;

    if (x <= 3.0e-10) {
        rt0 = 3.48198973061471E-02 - 4.09645850660395E-03 * x;
        rt1 = 3.81567185080042E-01 - 4.48902570656719E-02 * x;
        rt2 = 1.73730726945891E+00 - 2.04389090547327E-01 * x;
        rt3 = 1.18463056481549E+01 - 1.39368301742312E+00 * x;
        wt0 = 3.62683783378362E-01 - 3.13844305713928E-02 * x;
        wt1 = 3.13706645877886E-01 - 8.98046242557724E-02 * x;
        wt2 = 2.22381034453372E-01 - 1.29314370958973E-01 * x;
        wt3 = 1.01228536290376E-01 - 8.28299075414321E-02 * x;
    } else {
        ex = exp(-x);
        x1 = 1. / x;
        sx = sqrt(PIE4 * x1);
        y = x;
        z = x;
        if (x <= 20) {
            rt0 = 0;
            rt1 = 0;
            rt2 = 0;
            rt3 = 0;
            wt0 = 0;
            wt1 = 0;
            wt2 = 0;
            wt3 = 0;
            cr = 1;
            cw = 1;
            if (x <= 1.0) {
                p = FITTING_DATA + POLY4_1;
            } else if (x <= 5) {
                y = x - 3.0;
                z = y;
                p = FITTING_DATA + POLY4_5;
            } else if (x <= 10) {
                y = x - 7.5;
                z = y;
                p = FITTING_DATA + POLY4_10;
            } else if (x <= 15) {
                y = x - 12.5;
                z = x1;
                cw = ex;
                wt0 = sx;
                p = FITTING_DATA + POLY4_15;
            } else { // x <= 20
                y = x - 17.5;
                z = x1;
                cw = ex;
                wt0 = sx;
                p = FITTING_DATA + POLY4_20;
            }
        } else {
            rt0 = FITTING_DATA[POLY4_RBASE + 0] /
                  (x - FITTING_DATA[POLY4_RBASE + 0]);
            rt1 = FITTING_DATA[POLY4_RBASE + 1] /
                  (x - FITTING_DATA[POLY4_RBASE + 1]);
            rt2 = FITTING_DATA[POLY4_RBASE + 2] /
                  (x - FITTING_DATA[POLY4_RBASE + 2]);
            rt3 = FITTING_DATA[POLY4_RBASE + 3] /
                  (x - FITTING_DATA[POLY4_RBASE + 3]);
            wt0 = FITTING_DATA[POLY4_WBASE + 0] * sx;
            wt1 = FITTING_DATA[POLY4_WBASE + 1] * sx;
            wt2 = FITTING_DATA[POLY4_WBASE + 2] * sx;
            wt3 = FITTING_DATA[POLY4_WBASE + 3] * sx;
            cr = ex;
            if (x <= 35) {
                cr *= x1 * x1 * x1;
                if (x <= 25) {
                    p = FITTING_DATA + POLY4_25;
                } else { // x <= 35
                    p = FITTING_DATA + POLY4_35;
                }
            } else if (x <= 53) {
                p = FITTING_DATA + POLY4_53;
            }
            cw = cr;
        }
        if (x <= 53) {
            // rt0 += FP16(y)*cr; p += 16;
            // rt1 += FP16(y)*cr; p += 16;
            // rt2 += FP16(y)*cr; p += 16;
            // rt3 += FP16(y)*cr; p += 16;
            // wt0 += FP16(z)*cw; p += 16;
            // wt1 += FP16(y)*cr; p += 16;
            // wt2 += FP16(y)*cr; p += 16;
            // wt3 += FP16(y)*cr; p += 16;
            // if (x <= 20 && x > 10) {
            //     wt0 -= wt1 + wt2 + wt3;
            // }
            rt0 += FP16(y) * cr;
            p += 16;
            rt1 += FP16(y) * cr;
            p += 16;
            rt2 += FP16(y) * cr;
            p += 16;
            rt3 += FP16(y) * cr;
            p += 16;
            if (x <= 20 && x > 10) {
                wt0 += FP16(y) * cr;
            }
            p += 16;
            wt1 += FP16(y) * cr;
            p += 16;
            wt2 += FP16(y) * cr;
            p += 16;
            wt3 += FP16(y) * cr;
            p += 16;
            wt0 += FP16(z) * cw;
        }
    }
    rw[0] = rt0;
    rw[1] = rt1;
    rw[2] = rt2;
    rw[3] = rt3;
    rw[4] = wt0;
    rw[5] = wt1;
    rw[6] = wt2;
    rw[7] = wt3;
}

template <> __device__ inline void GINTrys_root<5>(double x, double *rw) {
    double rt0, rt1, rt2, rt3, rt4, wt0, wt1, wt2, wt3, wt4;
    double y, cr, ex, sx;
    const double *p;

    if (x < 3.e-10) {
        rt0 = 2.26659266316985E-02 - 2.15865967920897E-03 * x;
        rt1 = 2.31271692140903E-01 - 2.20258754389745E-02 * x;
        rt2 = 8.57346024118836E-01 - 8.16520023025515E-02 * x;
        rt3 = 2.97353038120346E+00 - 2.83193369647137E-01 * x;
        rt4 = 1.84151859759051E+01 - 1.75382723579439E+00 * x;
        wt0 = 2.95524224714752E-01 - 1.96867576909777E-02 * x;
        wt1 = 2.69266719309995E-01 - 5.61737590184721E-02 * x;
        wt2 = 2.19086362515981E-01 - 9.71152726793658E-02 * x;
        wt3 = 1.49451349150580E-01 - 1.02979262193565E-01 * x;
        wt4 = 6.66713443086877E-02 - 5.73782817488315E-02 * x;
    } else {
        if (x < 25) {
            rt0 = 0;
            rt1 = 0;
            rt2 = 0;
            rt3 = 0;
            rt4 = 0;
            wt0 = 0;
            wt1 = 0;
            wt2 = 0;
            wt3 = 0;
            wt4 = 0;
            cr = 1;
            if (x < 1.0) {
                y = x;
                p = FITTING_DATA + POLY5_1;
            } else if (x < 5.0) {
                y = x - 3.;
                p = FITTING_DATA + POLY5_5;
            } else if (x < 10.0) {
                y = x - 7.5;
                p = FITTING_DATA + POLY5_10;
            } else if (x < 15.0) {
                y = x - 12.5;
                p = FITTING_DATA + POLY5_15;
            } else if (x < 20.0) {
                y = x - 17.5;
                p = FITTING_DATA + POLY5_20;
            } else { // (x < 25.0)
                y = x - 22.5;
                p = FITTING_DATA + POLY5_25;
            }
        } else {
            ex = exp(-x);
            sx = sqrt(PIE4 / x);
            y = x;
            rt0 = FITTING_DATA[POLY5_RBASE + 0] /
                  (x - FITTING_DATA[POLY5_RBASE + 0]);
            rt1 = FITTING_DATA[POLY5_RBASE + 1] /
                  (x - FITTING_DATA[POLY5_RBASE + 1]);
            rt2 = FITTING_DATA[POLY5_RBASE + 2] /
                  (x - FITTING_DATA[POLY5_RBASE + 2]);
            rt3 = FITTING_DATA[POLY5_RBASE + 3] /
                  (x - FITTING_DATA[POLY5_RBASE + 3]);
            rt4 = FITTING_DATA[POLY5_RBASE + 4] /
                  (x - FITTING_DATA[POLY5_RBASE + 4]);
            wt0 = FITTING_DATA[POLY5_WBASE + 0] * sx;
            wt1 = FITTING_DATA[POLY5_WBASE + 1] * sx;
            wt2 = FITTING_DATA[POLY5_WBASE + 2] * sx;
            wt3 = FITTING_DATA[POLY5_WBASE + 3] * sx;
            wt4 = FITTING_DATA[POLY5_WBASE + 4] * sx;
            cr = ex;
            if (x < 40) {
                p = FITTING_DATA + POLY5_40;
            } else if (x < 59) {
                p = FITTING_DATA + POLY5_59;
            }
        }
        if (x < 59) {
            rt0 += FP17(y) * cr;
            p += 17;
            rt1 += FP17(y) * cr;
            p += 17;
            rt2 += FP17(y) * cr;
            p += 17;
            rt3 += FP17(y) * cr;
            p += 17;
            rt4 += FP17(y) * cr;
            p += 17;
            wt0 += FP17(y) * cr;
            p += 17;
            wt1 += FP17(y) * cr;
            p += 17;
            wt2 += FP17(y) * cr;
            p += 17;
            wt3 += FP17(y) * cr;
            p += 17;
            wt4 += FP17(y) * cr;
        }
    }
    rw[0] = rt0;
    rw[1] = rt1;
    rw[2] = rt2;
    rw[3] = rt3;
    rw[4] = rt4;
    rw[5] = wt0;
    rw[6] = wt1;
    rw[7] = wt2;
    rw[8] = wt3;
    rw[9] = wt4;
}

__device__ inline void _CINT_clenshaw_d1(
    int NROOTS, double &rr, const double *x, double u, int iroot) {
    /*
    reference
    https://github.com/sunqm/qcint/blob/38fa7cd87e5251e0bbb5abc549dbacc45f9da56e/src/polyfits.c
    */
    int i;
    double d0, d1, g0, g1;
    double u2 = u * 2.;
    if (NROOTS % 2 == 1 && iroot == NROOTS) {
        i = NROOTS - 1;
        d0 = 0;
        g0 = x[13 + 14 * i];
        d0 = u2 * g0 - d0 + x[12 + 14 * i];
        g0 = u2 * d0 - g0 + x[11 + 14 * i];
        d0 = u2 * g0 - d0 + x[10 + 14 * i];
        g0 = u2 * d0 - g0 + x[9 + 14 * i];
        d0 = u2 * g0 - d0 + x[8 + 14 * i];
        g0 = u2 * d0 - g0 + x[7 + 14 * i];
        d0 = u2 * g0 - d0 + x[6 + 14 * i];
        g0 = u2 * d0 - g0 + x[5 + 14 * i];
        d0 = u2 * g0 - d0 + x[4 + 14 * i];
        g0 = u2 * d0 - g0 + x[3 + 14 * i];
        d0 = u2 * g0 - d0 + x[2 + 14 * i];
        g0 = u2 * d0 - g0 + x[1 + 14 * i];
        rr = u * g0 - d0 + x[14 * i] * 0.5;
    } else {
        i = (iroot / 2) * 2;
        d0 = 0;
        d1 = 0;
        g0 = x[13 + 14 * i];
        g1 = x[13 + 14 + 14 * i];
        d0 = u2 * g0 - d0 + x[12 + 14 * i];
        d1 = u2 * g1 - d1 + x[12 + 14 + 14 * i];
        g0 = u2 * d0 - g0 + x[11 + 14 * i];
        g1 = u2 * d1 - g1 + x[11 + 14 + 14 * i];
        d0 = u2 * g0 - d0 + x[10 + 14 * i];
        d1 = u2 * g1 - d1 + x[10 + 14 + 14 * i];
        g0 = u2 * d0 - g0 + x[9 + 14 * i];
        g1 = u2 * d1 - g1 + x[9 + 14 + 14 * i];
        d0 = u2 * g0 - d0 + x[8 + 14 * i];
        d1 = u2 * g1 - d1 + x[8 + 14 + 14 * i];
        g0 = u2 * d0 - g0 + x[7 + 14 * i];
        g1 = u2 * d1 - g1 + x[7 + 14 + 14 * i];
        d0 = u2 * g0 - d0 + x[6 + 14 * i];
        d1 = u2 * g1 - d1 + x[6 + 14 + 14 * i];
        g0 = u2 * d0 - g0 + x[5 + 14 * i];
        g1 = u2 * d1 - g1 + x[5 + 14 + 14 * i];
        d0 = u2 * g0 - d0 + x[4 + 14 * i];
        d1 = u2 * g1 - d1 + x[4 + 14 + 14 * i];
        g0 = u2 * d0 - g0 + x[3 + 14 * i];
        g1 = u2 * d1 - g1 + x[3 + 14 + 14 * i];
        d0 = u2 * g0 - d0 + x[2 + 14 * i];
        d1 = u2 * g1 - d1 + x[2 + 14 + 14 * i];
        g0 = u2 * d0 - g0 + x[1 + 14 * i];
        g1 = u2 * d1 - g1 + x[1 + 14 + 14 * i];
        rr = iroot % 2 == 0 ? u * g0 - d0 + x[14 * i] * 0.5
                            : u * g1 - d1 + x[14 * i + 14] * 0.5;
    }
}

__device__ inline void polyfit_roots(
    int NROOTS, double x, double &u, double &w, int iroot) {
    // for nroots >= 6 only!
    if (x < 3.e-10) {
        int off = NROOTS * (NROOTS - 1) / 2 - 15;
        u = POLY_SMALLX_R0[off + iroot] + POLY_SMALLX_R1[off + iroot] * x;
        w = POLY_SMALLX_W0[off + iroot] + POLY_SMALLX_W1[off + iroot] * x;
        return;
    } else if (x > 35 + NROOTS * 5) {
        int off = NROOTS * (NROOTS - 1) / 2 - 15;
        double rt;
        rt = POLY_LARGEX_RT[off + iroot];
        u = rt / (x - rt);
        w = POLY_LARGEX_WW[off + iroot] * sqrt(PIE4 / x);
        return;
    }
    const double *datax = DATA_X + ((NROOTS - 1) * NROOTS / 2 - 15) * 14 * 31;
    const double *dataw = DATA_W + ((NROOTS - 1) * NROOTS / 2 - 15) * 14 * 31;
    int it;
    double tt;
    if (x <= 40) {
        it = (int)(x * .4);
        tt = (x - it * 2.5) * 0.8 - 1.;
    } else {
        x -= 40.;
        it = (int)(x * .25);
        tt = (x - it * 4.) * 0.5 - 1.;
        it += 16;
    }
    int offset = NROOTS * 14 * it;
    _CINT_clenshaw_d1(NROOTS, u, datax + offset, tt, iroot);
    _CINT_clenshaw_d1(NROOTS, w, dataw + offset, tt, iroot);
}

template <int NROOTS>
__device__ inline void GINTrys_root(double x, double &u, double &w, int iroot) {
    polyfit_roots(NROOTS, x, u, w, iroot);
}

template <>
__device__ void GINTrys_root<3>(double x, double &u, double &w, int iroot) {
    double rt0, rt1, rt2, wt0, wt1, wt2, t1, t2, t3, a1, a2, f1, f2;
    double y, z, cw, cr, ex, x1, sx;
    const double *p;

    if (x < 3.e-10) {
        rt0 = 6.03769246832797E-02 - 9.28875764357368E-03 * x;
        rt1 = 7.76823355931043E-01 - 1.19511285527878E-01 * x;
        rt2 = 6.66279971938567E+00 - 1.02504611068957E+00 * x;
        wt0 = 4.67913934572691E-01 - 5.64876917232519E-02 * x;
        wt1 = 3.60761573048137E-01 - 1.49077186455208E-01 * x;
        wt2 = 1.71324492379169E-01 - 1.27768455150979E-01 * x;
    } else {
        ex = exp(-x);
        x1 = 1. / x;
        sx = sqrt(PIE4 * x1);
        if (x < 33.) {
            y = x;
            z = x;
            rt0 = 0;
            rt1 = 0;
            rt2 = 0;
            wt0 = 0;
            cr = 1.;
            if (x < 5.) {
                if (x < 1.) {
                    p = FITTING_DATA + POLY3_1;
                } else if (x < 3.) {
                    y = x - 2.0;
                    z = y;
                    p = FITTING_DATA + POLY3_3;
                } else { // x < 5
                    y = x - 4.0;
                    z = y;
                    p = FITTING_DATA + POLY3_5;
                }
            } else {
                cw = ex;
                wt0 = sx;
                if (x < 10.) {
                    y = x - 7.5;
                    z = x1;
                    p = FITTING_DATA + POLY3_10;
                } else if (x < 15) {
                    y = x - 12.5;
                    z = x1;
                    p = FITTING_DATA + POLY3_15;
                } else {
                    cr = ex * x1 * x1;
                    if (x < 20) {
                        cr *= x1;
                        p = FITTING_DATA + POLY3_20;
                    } else { // x < 33
                        p = FITTING_DATA + POLY3_33;
                    }
                    cw = cr;
                    rt0 = FITTING_DATA[POLY3_RBASE + 0] /
                          (x - FITTING_DATA[POLY3_RBASE + 0]);
                    rt1 = FITTING_DATA[POLY3_RBASE + 1] /
                          (x - FITTING_DATA[POLY3_RBASE + 1]);
                    rt2 = FITTING_DATA[POLY3_RBASE + 2] /
                          (x - FITTING_DATA[POLY3_RBASE + 2]);
                }
            }

            rt0 += FP14(y) * cr;
            p += 14;
            rt1 += FP14(y) * cr;
            p += 14;
            rt2 += FP14(y) * cr;
            p += 14;
            f2 = FP14(z);

            if (x < 5.) {
                f1 = ((x + x) * f2 + ex) / 3.;
                wt0 = (x + x) * f1 + ex;
            } else {
                wt0 += f2 * cw;
                f1 = (wt0 - ex) * x1 * .5;
                f2 = (f1 * 3 - ex) * x1 * .5;
            }

            t1 = rt0 / (rt0 + 1.);
            t2 = rt1 / (rt1 + 1.);
            t3 = rt2 / (rt2 + 1.);
            a1 = f1 - t1 * wt0;
            a2 = f2 - t1 * f1;
            wt1 = (t3 * a1 - a2) / ((t3 - t2) * (t2 - t1));
            wt2 = (a2 - t2 * a1) / ((t3 - t2) * (t3 - t1));
            wt0 -= wt1 + wt2;
        } else { // x >= 33
            rt0 = FITTING_DATA[POLY3_RBASE + 0] /
                  (x - FITTING_DATA[POLY3_RBASE + 0]);
            rt1 = FITTING_DATA[POLY3_RBASE + 1] /
                  (x - FITTING_DATA[POLY3_RBASE + 1]);
            rt2 = FITTING_DATA[POLY3_RBASE + 2] /
                  (x - FITTING_DATA[POLY3_RBASE + 2]);
            wt0 = FITTING_DATA[POLY3_WBASE + 0] * sx;
            wt1 = FITTING_DATA[POLY3_WBASE + 1] * sx;
            wt2 = FITTING_DATA[POLY3_WBASE + 2] * sx;
            if (x < 47.) {
                p = FITTING_DATA + POLY3_47;
                rt0 += FP4(x) * ex;
                p += 4;
                rt1 += FP4(x) * ex;
                p += 4;
                rt2 += FP4(x) * ex;
                p += 4;
                wt0 += FP4(x) * ex;
                p += 4;
                wt1 += FP4(x) * ex;
                p += 4;
                wt2 += FP4(x) * ex;
            }
        }
    }
    switch (iroot) {
    case 0:
        u = rt0;
        w = wt0;
        break;
    case 1:
        u = rt1;
        w = wt1;
        break;
    case 2:
        u = rt2;
        w = wt2;
        break;
    }
}

template <>
__device__ void GINTrys_root<4>(double x, double &u, double &w, int iroot) {
    double y, z, cr, cw, ex, x1, sx;
    const double *p;

    if (x <= 3.0e-10) {
        switch (iroot) {
        case 0:
            u = 3.48198973061471E-02 - 4.09645850660395E-03 * x;
            w = 3.62683783378362E-01 - 3.13844305713928E-02 * x;
            break;
        case 1:
            u = 3.81567185080042E-01 - 4.48902570656719E-02 * x;
            w = 3.13706645877886E-01 - 8.98046242557724E-02 * x;
            break;
        case 2:
            u = 1.73730726945891E+00 - 2.04389090547327E-01 * x;
            w = 2.22381034453372E-01 - 1.29314370958973E-01 * x;
            break;
        case 3:
            u = 1.18463056481549E+01 - 1.39368301742312E+00 * x;
            w = 1.01228536290376E-01 - 8.28299075414321E-02 * x;
            break;
        }
    } else {
        ex = exp(-x);
        x1 = 1. / x;
        sx = sqrt(PIE4 * x1);
        y = x;
        z = x;
        if (x <= 20) {
            u = 0;
            w = 0;
            cr = 1;
            cw = 1;
            if (x <= 1.0) {
                p = FITTING_DATA + POLY4_1;
            } else if (x <= 5) {
                y = x - 3.0;
                z = y;
                p = FITTING_DATA + POLY4_5;
            } else if (x <= 10) {
                y = x - 7.5;
                z = y;
                p = FITTING_DATA + POLY4_10;
            } else if (x <= 15) {
                y = x - 12.5;
                z = x1;
                cw = ex;
                if (iroot == 0)
                    w = sx;
                p = FITTING_DATA + POLY4_15;
            } else { // x <= 20
                y = x - 17.5;
                z = x1;
                cw = ex;
                if (iroot == 0)
                    w = sx;
                p = FITTING_DATA + POLY4_20;
            }
        } else {
            u = FITTING_DATA[POLY4_RBASE + iroot] /
                (x - FITTING_DATA[POLY4_RBASE + iroot]);
            w = FITTING_DATA[POLY4_WBASE + iroot] * sx;
            cr = ex;
            if (x <= 35) {
                cr *= x1 * x1 * x1;
                if (x <= 25) {
                    p = FITTING_DATA + POLY4_25;
                } else { // x <= 35
                    p = FITTING_DATA + POLY4_35;
                }
            } else if (x <= 53) {
                p = FITTING_DATA + POLY4_53;
            }
            cw = cr;
        }
        if (x <= 53) {
            p += 16 * iroot;
            u += FP16(y) * cr;
            p += 64;
            if (iroot != 0 || (iroot == 0 && x <= 20 && x > 10))
                w += FP16(y) * cr;
            if (iroot == 0) {
                p += 64;
                w += FP16(z) * cw;
            }
        }
    }
}

template <>
__device__ void GINTrys_root<5>(double x, double &u, double &w, int iroot) {
    double y, cr, ex, sx;
    const double *p;

    if (x < 3.e-10) {
        switch (iroot) {
        case 0:
            u = 2.26659266316985E-02 - 2.15865967920897E-03 * x;
            w = 2.95524224714752E-01 - 1.96867576909777E-02 * x;
            break;
        case 1:
            u = 2.31271692140903E-01 - 2.20258754389745E-02 * x;
            w = 2.69266719309995E-01 - 5.61737590184721E-02 * x;
            break;
        case 2:
            u = 8.57346024118836E-01 - 8.16520023025515E-02 * x;
            w = 2.19086362515981E-01 - 9.71152726793658E-02 * x;
            break;
        case 3:
            u = 2.97353038120346E+00 - 2.83193369647137E-01 * x;
            w = 1.49451349150580E-01 - 1.02979262193565E-01 * x;
            break;
        case 4:
            u = 1.84151859759051E+01 - 1.75382723579439E+00 * x;
            w = 6.66713443086877E-02 - 5.73782817488315E-02 * x;
            break;
        }
    } else {
        if (x < 25) {
            u = 0;
            w = 0;
            cr = 1;
            if (x < 1.0) {
                y = x;
                p = FITTING_DATA + POLY5_1;
            } else if (x < 5.0) {
                y = x - 3.;
                p = FITTING_DATA + POLY5_5;
            } else if (x < 10.0) {
                y = x - 7.5;
                p = FITTING_DATA + POLY5_10;
            } else if (x < 15.0) {
                y = x - 12.5;
                p = FITTING_DATA + POLY5_15;
            } else if (x < 20.0) {
                y = x - 17.5;
                p = FITTING_DATA + POLY5_20;
            } else { // (x < 25.0)
                y = x - 22.5;
                p = FITTING_DATA + POLY5_25;
            }
        } else {
            ex = exp(-x);
            sx = sqrt(PIE4 / x);
            y = x;
            u = FITTING_DATA[POLY5_RBASE + iroot] /
                (x - FITTING_DATA[POLY5_RBASE + iroot]);
            w = FITTING_DATA[POLY5_WBASE + iroot] * sx;
            cr = ex;
            if (x < 40) {
                p = FITTING_DATA + POLY5_40;
            } else if (x < 59) {
                p = FITTING_DATA + POLY5_59;
            }
        }
        if (x < 59) {
            p += 17 * iroot;
            u += FP17(y) * cr;
            p += 17 * 5;
            w += FP17(y) * cr;
        }
    }
}
